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
|
-- statusd_netmon.lua: monitor the speed of a network interface
--
-- Thanx to Tuomo for pointing out a problem in the previous script.
--
-- In case this doesn't work for someone, do let me know :)
--
-- Author
-- Sadrul Habib Chowdhury (Adil)
-- imadil at gmail dot com
local defaults = {
device = "eth0",
show_avg = 1, -- show average stat?
avg_sec = 60, -- default, shows average of 1 minute
show_count = 0, -- show tcp connection count?
interval = 1*1000 -- update every second
}
local timer = nil -- the timer
local positions = {} -- positions where the entries will be
local last = {} -- the last readings
local history_in = {} -- history to calculate the average
local history_out = {}
local total_in, total_out = 0, 0
local counter = 0 --
local settings = table.join(statusd.get_config("netmon"), defaults)
--
-- tokenize the string
--
local function tokenize(str)
local ret = {}
local i = 0
local k = nil
for k in string.gfind(str, '(%w+)') do
ret[i] = k
i = i + 1
end
return ret
end
--
-- get the connection count
--
local function get_connection_count()
-- local f = io.popen('netstat -st | grep -e "[0-9]\\+ connections established" | sed s/"[ ]\\+\\([0-9]\\+\\) connections established"/\\\\1/', 'r')
local f = io.popen('netstat -st | grep "connections established"', 'r')
if not f then return 'q' end
local ret = f:read('*a')
ret = string.gsub(ret, '%s*(%d+).+', '%1')
f:close()
return tostring(ret)
end
--
-- calculate the average
--
local function calc_avg(lin, lout)
if counter == settings.avg_sec then
counter = 0
end
total_in = total_in - history_in[counter] + lin
history_in[counter] = lin
total_out = total_out - history_out[counter] + lout
history_out[counter] = lout
counter = counter + 1
return string.format("%.1fK/%.1fK", total_in/settings.avg_sec, total_out/settings.avg_sec)
end
--
-- parse the information
--
local function parse_netmon_info()
local s
local lin, lout
for s in io.lines('/proc/net/dev') do
local f = string.find(s, settings.device)
if f then
local t = tokenize(s)
return t[positions[0]], t[positions[1]]
end
end
return nil, nil
end
--
-- update the netmon monitor
--
local function update_netmon_info()
local s
local lin, lout
lin, lout = parse_netmon_info()
if not lin or not lout then
-- you should never reach here
statusd.inform("netmon", "oops")
statusd.inform("netmon_hint", "critical")
return
end
last[0], lin = lin, lin - last[0]
last[1], lout = lout, lout - last[1]
local output = string.format("%.1fK/%.1fK", lin/1024, lout/1024)
if settings.show_avg == 1 then
output = output .. " (" .. calc_avg(lin/1024, lout/1024) .. ")"
end
if settings.show_count == 1 then
output = "[" .. get_connection_count().."] " .. output
end
statusd.inform("netmon", output)
timer:set(settings.interval, update_netmon_info)
end
--
-- is everything ok to begin with?
--
local function sanity_check()
local f = io.open('/proc/net/dev', 'r')
local e
if not f then
return false
end
local s = f:read('*line')
s = f:read('*line') -- the second line, which should give
-- us the positions of the info we seek
local t = tokenize(s)
local n = table.getn(t)
local i = 0
for i = 0,n do
if t[i] == "bytes" then
positions[0] = i
break
end
end
i = positions[0] + 1
for i=i,n do
if t[i] == "bytes" then
positions[1] = i
break
end
end
if not positions[0] or not positions[1] then
return false
end
s = f:read('*a') -- read the whole file
if not string.find(s, settings.device) then
return false -- the device does not exist
end
return true
end
--
-- start the timer
--
local function init_netmon_monitor()
if sanity_check() then
timer = statusd.create_timer()
last[0], last[1] = parse_netmon_info()
if settings.show_avg == 1 then
for i=0,settings.avg_sec-1 do
history_in[i], history_out[i] = 0, 0
end
end
statusd.inform("netmon_template", "xxxxxxxxxxxxxxxxxxxxxxx")
update_netmon_info()
else
statusd.inform("netmon", "oops")
statusd.inform("netmon_hint", "critical")
end
end
init_netmon_monitor()
|