1 -- Authors: Vladimir Chizhov <jagoterr@gmail.com>
3 -- Last Changed: 2005-03-29
5 -- filename : statusd_sysmon.lua
9 -- system monitor for Ion3 WM statusbar
10 -- Written by Vladimir Chizhov < jagoterr *at* gmail *dot* com >
11 -- I'll apreciate any comments, bug reports and feature requests :)
13 -- Shows memory, swap and filesystem statistics, based on 'free' and 'df' commands output.
14 -- Allows lua-expression evaluation with the values.
16 -- This script can work not only as a Ion3 statusd monitor, but also as a standalone script.
17 -- If it works as a Ion statusd monitor, it reads user settings from statusd.
19 if not statusd_sysmon
then
28 -- %% - percents symbol (%)
29 -- ${expression} - evaluates lua expression
30 -- Shortly about expressions:
31 -- - may contain all macroses (of format %macros_name or
32 -- %{macros_name macros_params*})
33 -- - may contain global function calls
34 -- - may contain arithmetic, logical operations etc.
35 -- - there is a global function 'dpr' defined in this script
36 -- for decreasing double numbers' precision (see this
37 -- function comments for more information and the example templates)
40 -- %mem_total - total available memory
41 -- %mem_used - used memory
42 -- %mem_free - free memory
43 -- %mem_buffers - buffered memory
44 -- %mem_cached - cached memory
45 -- %mem_shared - shared memory
48 -- %swap_total - total available swap space
49 -- %swap_used - used swap space
50 -- %swap_free - free swap space
53 -- %{fs_total mount_point} - total available space on filesystem
54 -- %{fs_used mount_point} - used space on filesystem
55 -- %{fs_free mount_point} - free space on filesystem
59 -- simple swap statistics
60 -- template = "swap used %swap_used of %swap_total"
62 -- used swap in percents with one sign after comma!
63 -- how? so... try to understand, I think it's not very hard, if you read the previous comments
64 -- template = "swap used by ${dpr (%swap_used / %swap_total * 100)}%%"
66 -- RAM used, excluding buffers and cached memory
67 -- template = "RAM used: ${%mem_used - %mem_buffers - %mem_cached}"
69 -- root filesystem simple info
70 -- note, that you should specify the actual mount point for filesystem, accordingly to /etc/mtab
71 -- template = "/ used by %{fs_used /} of %{fs_total /}"
75 template
= "RAM: %mem_used / %mem_total MB (${dpr (%mem_used / %mem_total * 100, 1)} %%) * SWAP: %swap_used / %swap_total MB (${dpr (%swap_used / %swap_total * 100, 1)} %%) * /: %{fs_used /} / %{fs_total /} (${dpr (%{fs_used /} / %{fs_total /} * 100, 1)} %%)",
77 -- DIMENSION for monitors
84 -- dimension for RAM and SWAP
87 -- dimension for filesystems
94 if statusd
~= nil then
95 settings
= table.join (statusd
.get_config ("sysmon"), statusd_sysmon
)
97 settings
= statusd_sysmon
109 -- --------------------------------------------------------------------------
110 -- Decreases the precision of the floating number
111 -- @param number the number to decrease it's precision
112 -- @param signs_q the quantity of signs after the comma to be left
113 function dpr (number, signs_q
)
114 local pattern
= "%d+"
115 if signs_q
== nil then
119 pattern
= pattern
.."%."
121 for i
= 1, tonumber (signs_q
) do
122 pattern
= pattern
.."%d"
124 return string.gsub (number, "("..pattern
..")(.*)", "%1")
127 -- --------------------------------------------------------------------------
128 -- Retrieves information from 'free' command output
129 local function parse_free_command ()
130 local f
= io
.popen ('free -'..settings
.mem_dimension
, 'r')
131 local s
= f
:read('*a')
142 = string.find(s
, 'Mem:%s*(%d+)%s+(%d+)%s+(%d+)%s+(%d+)%s+(%d+)%s+(%d+)')
147 = string.find(s
, 'Swap:%s*(%d+)%s+(%d+)%s+(%d+)')
150 -- --------------------------------------------------------------------------
151 -- Retrieves information from 'df' command output
152 local function parse_df_command ()
153 local factor
= factors
[settings
.fs_dimension
]
154 local f
= io
.popen ('df --block-size=1 -P', 'r')
155 -- local s = f:read ("*l")
156 for line
in f
:lines () do
157 local st
, en
, fs
, total
, used
, free
, mount_point
=
158 string.find (line
, '(%S+)%s+(%d+)%s+(%d+)%s+(%d+)%s+[%-%d]-%%?%s+(.*)')
160 metrics
["fs_total->"..mount_point
] = string.gsub (total
/ factor
, '(%d+%.%d%d)(.*)', "%1")
161 metrics
["fs_used->"..mount_point
] = string.gsub (used
/ factor
, '(%d+%.%d%d)(.*)', "%1")
162 metrics
["fs_free->"..mount_point
] = string.gsub (free
/ factor
, '(%d+%.%d%d)(.*)', "%1")
171 -- --------------------------------------------------------------------------
172 -- Main calculating of values, template parsing and Ion statusd updating
173 local function update_sysmon ()
174 local sysmon_st
= settings
.template
176 parse_free_command ()
180 -- filling the template by actual values
181 sysmon_st
= string.gsub (sysmon_st
, "%%%{([%w%_]+)%s+(%S-)%}", function (arg1
, arg2
)
182 return(metrics
[arg1
.."->"..arg2
] or "")
184 sysmon_st
= string.gsub (sysmon_st
, "%%([%w%_]+)", function (arg1
)
185 return (metrics
[arg1
] or "")
187 sysmon_st
= string.gsub (sysmon_st
, "%$%{(.-)%}", function (arg1
)
188 return loadstring("return "..arg1
)()
190 -- replacing the '%%' macros with the '%' symbol
191 sysmon_st
= string.gsub (sysmon_st
, "%%%%", "%%")
193 if statusd
~= nil then
194 statusd
.inform ("sysmon_template", sysmon_st
)
195 statusd
.inform ("sysmon", sysmon_st
)
196 sysmon_timer
:set (settings
.interval
, update_sysmon
)
198 io
.stdout
:write (sysmon_st
.."\n")
202 -- --------------------------------------------------------------------------
204 if statusd
~= nil then
205 sysmon_timer
= statusd
.create_timer ()