1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212
|
-- Authors: Antti Vähäkotamäki
-- License: LGPL, version 2.1 or later
-- Last Changed: 2006
--
-- statusd_exec.lua
--
--
-- -- What is this?
--
-- This is a simple "general" statusd Lua script which
-- lets you show output of external programs in ion
-- statusbar. This is convenient if you are not familiar
-- with Lua but can handle yourself with some other
-- language enough to output what you would want the
-- statusbar to show.
--
-- After this script is loaded it starts executing all
-- the provided programs (wether a placeholder exists in
-- template or not) and updates the statusbar every time
-- one of them prints (and flushes) a line.
--
-- -- How to use it?
--
-- 1 ) update statusbar template to include %exec_something
-- 2 ) specify parameters in cfg_statusbar.lua like this:
--
-- mod_statusbar.launch_statusd{
--
-- [ ... some other config here ... ],
--
-- exec = {
--
-- -- show date each second in %exec_date with.. date!
--
-- date = {
-- program = 'date',
-- retry_delay = 1 * 1000,
-- },
--
-- -- show percentage of hda1 every 30 seconds in
-- -- %exec_hda1u with df, grep and sed.
-- -- also highlights entry if usage is high.
--
-- hda1u = {
-- program = 'df|grep hda1|sed "s/.*\\(..%\\).*/\\1/"',
-- retry_delay = 30 * 1000,
-- meter_length = 4,
-- hint_regexp = {
-- important = '9[456].',
-- critical = {
-- '9[789].',
-- '1...',
-- },
-- },
-- },
--
-- -- keep continous track of a remote machine in
-- -- %exec_remote with ssh, bash and uptime.
-- -- if the connection breaks, wait 60 seconds and retry
--
-- remote = {
-- program = 'ssh -tt myhost.com "while (uptime);' ..
-- 'do sleep 1; done"',
-- retry_delay = 60 * 1000,
-- },
-- }
-- }
--
-- -- Description of variables:
--
-- * program
-- The program to execute. The last line of each
-- flushed output this program writes to stdout is
-- inserted as the content of the meter.
--
-- * retry_delay (optional)
-- The delay to wait (ms) before running the program again
-- once it stops sending data. Some programs just
-- send the data and exit while others continue
-- sending data periodically. This value can be used
-- to control the update rate for the first type of
-- programs. You can also specify a value for the other
-- type of programs to retry if the program stops for
-- some reason.
--
-- * meter_length (optional)
-- The space reserved for this meter in characters.
-- If the value is not specified or is less than 1
-- then the space is determined by the length of the
-- data being shown but some people do not want their
-- statusbar width to change randomly.
--
-- * hint_regexp (optional)
-- These regular expressions (in Lua syntax) are
-- matched with the data and in case of a match the
-- named hint is set to the meter. The value can be
-- either a string containing the regexp or a table
-- containing several possible regexps (Lua regexp
-- doesn't have an 'or'). By default the themes define
-- a color for 'important' and 'critical' hints.
--
--
local settings = table.join( statusd.get_config("exec"), {} )
local start_execution = nil
local timers = {}
-- Function for starting and restarting execution of a process
start_execution = function ( key )
-- Set up a function for receiving the data
-- and informing the statusbar
local process_input = function ( new_data )
local received_data = ""
-- When we get new data, output the last complete line
while new_data do
received_data = received_data .. new_data
-- Erase old data which we do not need anymore
received_data = string.gsub( received_data,
".*\n(.*\n.*)", "%1" )
-- Set the last complete line as the current line
local current_line = string.gsub( received_data,
"(.*)\n.*", "%1" )
local t_key = "exec_" .. key
local t_length = settings[key].meter_length
local h_regexp = settings[key].hint_regexp
if not tlength or t_length < 1 then
t_length = string.len( current_line )
end
statusd.inform( t_key .. "_hint", '' )
statusd.inform( t_key .. "_template",
string.rep( 'x', t_length ) )
statusd.inform( t_key, current_line )
if not h_regexp then h_regexp = {} end
for hint, re in pairs( h_regexp ) do
if ( type( re ) == 'string' ) then
re = { re }
end
for _, r in ipairs( re ) do
if ( string.find( current_line, r ) ) then
statusd.inform(t_key .. "_hint", hint)
end
end
end
-- Wait for bgread to signal that more data
-- is available or the program has exited
new_data = coroutine.yield()
end
-- Program has exited.
-- Start a timer for a new execution if set.
if settings[key].retry_delay then
timers[key]:set( settings[key].retry_delay,
function()
start_execution(key)
end )
end
end
-- Set up a simple function for printing errors
local process_error = function( new_data )
while new_data do
io.stderr:write( "ion-statusd [statusd_exec, key='"
.. key .. "']: " .. new_data )
io.stderr:flush()
new_data = coroutine.yield()
end
end
-- Execute the program in the background and create
-- coroutine functions to handle input and error data
statusd.popen_bgread( settings[key].program,
coroutine.wrap( process_input ),
coroutine.wrap( process_error ) )
end
-- Now start execution of all defined processes
for key in pairs(settings) do
timers[key] = statusd.create_timer()
start_execution(key)
end
--
-- Copyright (c) Antti Vähäkotamäki 2006.
--
-- Ion is free software; you can redistribute it and/or modify it under
-- the terms of the GNU Lesser General Public License as published by
-- the Free Software Foundation; either version 2.1 of the License, or
-- (at your option) any later version.
--
|