├── README.md └── init.lua /README.md: -------------------------------------------------------------------------------- 1 | #lognotify... 2 | ... is log watcher for awesome wm. 3 | 4 | It will show a naughty popup each time something 5 | changes in one of the predefined log files. 6 | 7 | #REQUIREMENTS 8 | [awesome](http://awesome.naquadah.org/) for sure :) 9 | 10 | [linotify](https://github.com/hoelzro/linotify) 11 | 12 | $ luarocks install inotify 13 | 14 | [luasocket](http://luasocket.luaforge.net/) 15 | 16 | $ luarocks install luasocket 17 | 18 | [bitop](http://bitop.luajit.org/) 19 | 20 | $ luarocks install luabitop 21 | 22 | One-Liner for archlinux: 23 | 24 | $ yaourt -S lua-socket lua-bitop linotify-git 25 | 26 | #SETUP 27 | * Make and install luainotify. 28 | * Clone lognotify into your configuration directory. (~/.config/awesome): 29 | 30 | `cd $XDG_CONFIG_HOME/awesome && git clone git://github.com/Mic92/lognotify.git` 31 | 32 | or rename init.lua to lognotify.lua and put into awesome's loadpath: 33 | 34 | `wget --no-check-certificate https://github.com/Mic92/lognotify/blob/master/init.lua -O $XDG_CONFIG_HOME/awesome/lognotify.lua` 35 | 36 | #USAGE 37 | * Require the module in your rc.lua 38 | 39 | `local lognotify = require("lognotify")` 40 | 41 | * Initialize and configure it. Here an example: 42 | 43 | ``` lua 44 | ilog = lognotify{ 45 | logs = { mpd = { file = "/home/bob/.mpd/log", }, 46 | aptitude = { file = "/var/log/aptitude", }, 47 | -- Check, whether you have the permissions to read your log files! 48 | -- You can fix this by configure syslog deamon in many case. 49 | syslog = { file = "/var/log/syslog", ignore = { "Changing fan level" }, 50 | }, 51 | awesome = { file = "/home/bob/log/awesome", 52 | ignore = { 53 | "/var/lib/dpkg", -- aptwidget failure when aptitude running 54 | "wicd", "wired profiles found", -- wicd junk 55 | "seek to:", "Close unzip stream", -- gmpc junk 56 | "^nolog"}, 57 | }, 58 | -- Delay between checking in seconds. Default: 1 59 | interval = 1, 60 | -- Time in seconds after which popup expires. Set 0 for no timeout. Default: 0 61 | naughty_timeout = 15 62 | } 63 | ``` 64 | 65 | * run it: 66 | 67 | ` 68 | ilog:start() 69 | ` 70 | 71 | * if you tired of it, you can stop it and start later at any time again 72 | 73 | ` 74 | ilog:stop() 75 | ` 76 | 77 | #THANKS 78 | 79 | * [koniu](https://github.com/koniu) - original author of code 80 | * [dodo](https://github.com/dodo) - port to luarocks's inotify and fixes related to logrotate 81 | -------------------------------------------------------------------------------- /init.lua: -------------------------------------------------------------------------------- 1 | -- _ _ _ __ 2 | -- | | | | (_)/ _| 3 | -- | | ___ __ _ _ __ ___ | |_ _| |_ _ _ 4 | -- | |/ _ \ / _` | '_ \ / _ \| __| | _| | | | 5 | -- | | (_) | (_| | | | | (_) | |_| | | | |_| | 6 | -- |_|\___/ \__, |_| |_|\___/ \__|_|_| \__, | 7 | -- __/ | __/ | 8 | -- |___/ |___/ 9 | -- 10 | -- log watcher for awesome wm 11 | -- show a naughty popup each time something 12 | -- changes in one of the predefined log files. 13 | -- 14 | -- based on work of koniu gmail.com> 15 | -- (see https://awesome.naquadah.org/wiki/Naughty_log_watcher) 16 | -- 17 | -- Copyright (c) 2011-2012, Jörg Thalheim 18 | -- 19 | -- This program is free software. It comes without any warranty, to 20 | -- the extent permitted by applicable law. You can redistribute it 21 | -- and/or modify it under the terms of the Do What The Fuck You Want 22 | -- To Public License, Version 2, as published by Sam Hocevar. See 23 | -- http://sam.zoy.org/wtfpl/COPYING for more details. 24 | 25 | -- {{{ Grab enviroment 26 | -- standart library 27 | local io = io and { open = io.open } or require("io") 28 | local bit = bit32 or bit or require('bit') 29 | local ipairs = ipairs 30 | local pairs = pairs 31 | local print = print 32 | local setmetatable = setmetatable 33 | local timer = (type(timer) == 'table' and timer or require("gears.timer")) 34 | local type = type 35 | -- external 36 | local socket = require("socket") 37 | local inotify = require("inotify") 38 | local escape = awful and awful.util.escape or require("awful.util").escape 39 | local naughty = naughty or require("naughty") 40 | -- }}} 41 | 42 | local lognotify = {} 43 | 44 | LOGNOTIFY = {} 45 | LOGNOTIFY_mt = { __index = LOGNOTIFY } 46 | 47 | function lognotify.new(settings) 48 | local watcher = {} 49 | if type(settings) ~= "table" then settings = {} end 50 | 51 | watcher.logs = settings.logs or {} 52 | watcher.naughty_timeout = settings.naughty_timeout or 0 53 | watcher.timer = timer({ timeout = settings.interval or 1}) 54 | 55 | setmetatable(watcher, LOGNOTIFY_mt) 56 | 57 | return watcher 58 | end 59 | 60 | function LOGNOTIFY:start() 61 | local errno, errstr 62 | self.inotify, errno, errstr = inotify.init() 63 | self.sd = { getfd = function () return self.inotify:fileno() end } 64 | for logname, log in pairs(self.logs) do 65 | self:read_log(logname) 66 | self:watch_log(logname) 67 | end 68 | if self.timer.connect_signal then 69 | self.timer:connect_signal("timeout", function() self:watch() end) 70 | else 71 | self.timer:add_signal("timeout", function() self:watch() end) 72 | end 73 | self.timer:start() 74 | end 75 | 76 | function LOGNOTIFY:stop() 77 | self.timer:stop() 78 | self.inotify:close() 79 | end 80 | 81 | function LOGNOTIFY:watch() 82 | if #socket.select({self.sd}, nil, 0) > 0 then 83 | local events, nread, errno, errstr = self.inotify:read() 84 | if events then 85 | for i, event in ipairs(events) do 86 | for logname, log in pairs(self.logs) do 87 | if event.wd == log.wd then 88 | if bit.band(event.mask, inotify.IN_MOVE_SELF) ~= 0 then 89 | self:watch_log(logname) 90 | end 91 | local diff = self:read_log(logname) 92 | if diff then 93 | self:notify(logname, log.file, diff) 94 | end 95 | end 96 | end 97 | end 98 | end 99 | end 100 | end 101 | 102 | function LOGNOTIFY:watch_log(logname) 103 | local log = self.logs[logname] 104 | if log.wd then 105 | self.inotify:rmwatch(log.wd) 106 | end 107 | log.wd, errno, errstr = self.inotify:addwatch(log.file, 108 | inotify.IN_MODIFY, 109 | inotify.IN_MOVE_SELF) 110 | log.len = nil 111 | self:read_log(logname) 112 | end 113 | 114 | function LOGNOTIFY:read_log(logname) 115 | local log = self.logs[logname] 116 | 117 | -- read log file 118 | local f, errno = io.open(log.file) 119 | if not f then 120 | print("[lognotify] Can't read: "..errno) 121 | return 122 | end 123 | 124 | -- log was visited earlier 125 | if not log.len then 126 | log.len = f:seek("end") 127 | f:close() 128 | return 129 | end 130 | f:seek("set", log.len) 131 | -- remove trailing newline 132 | local diff = f:read("*a"):gsub("\n$", "") 133 | 134 | -- set last length 135 | log.len = f:seek("end") 136 | f:close() 137 | 138 | -- check if ignored 139 | local ignored = false 140 | for i, phr in ipairs(log.ignore or {}) do 141 | if diff:find(phr) then ignored = true; break end 142 | end 143 | 144 | if not ignored then 145 | return diff 146 | end 147 | end 148 | 149 | function LOGNOTIFY:notify(name,file,diff) 150 | naughty.notify{ 151 | title = name..": "..file, 152 | text = escape(diff), 153 | hover_timeout = 0.2, timeout = self.naughty_timeout 154 | } 155 | end 156 | 157 | 158 | return setmetatable(lognotify, { __call = function(self, ...) return self.new(...) end }) 159 | -- vim:filetype=lua:tabstop=8:shiftwidth=4:expandtab: 160 | --------------------------------------------------------------------------------