After reading the answer by MelBurslan and various comments, I decided to try (inspired by their suggestions) to do a version in Lua. This was done in Lua 5.1.5 - I'm not sure if it will work with the latest Lua.
The general idea is to use Lua's popen
(open a pipe) to execute top
and then process the resulting data using a regular expression (or pattern, as it is called in Lua). Matching lines (which would be most of them) are then considered for crossing the threshold percentage. If they do, they are added to a table.
If the table is not empty, then zenity
is called to display a message to the user. A few "gotchas" I found during development:
- I added a timeout of 60 seconds to zenity so that, if you were not at the PC at the time, you didn't fill the screen with warning dialogs.
- I added
--display=:0.0
so that a display screen was found when running under cron
.
I simplified the test for "every 15 minutes" in the crontab, like this:
*/15 * * * * /home/nick/check_cpu_usage.lua
The regular expression captures everything from top
in case you want to do other tests (eg. using too much memory).
I think this would be faster than firing off lots of processes and subshells. It seems to work OK. Test by reducing the threshold (eg. to 5) and change the crontab entry to check every minutes.
check_cpu_usage.lua
#! /usr/local/bin/lua
THRESHOLD = 90 -- percent
-- pipe output of top through a file "f"
f = assert (io.popen ("top -b -n 1 -w 512"))
t = { }
-- check each line
for line in f:lines() do
-- match top output, eg.
-- PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND
-- 30734 nick 20 0 6233848 3.833g 3.731g S 8.6 12.2 3:11.75 VirtualBox
local pid, user, priority, nice, virt, res, shr,
status, cpu, mem, time, command =
string.match (line,
"^%s*(%d+)%s+(%a+)%s+(%-?%d+)%s+(%-?%d+)" ..
-- pid user priority nice
"%s+([%d.]+[g]?)%s+([%d.]+[g]?)%s+([%d.]+[g]?)%s+([DRSTZ])%s+(%d+%.%d+)%s+(%d+%.%d+)" ..
-- virtual res shr status %cpu %mem
"%s+([0-9:.]+)%s+(.*)$")
-- time command
-- if a match (first few lines won't) check for CPU threshold
if pid then
cpu = tonumber (cpu)
if cpu >= THRESHOLD then
table.insert (t, string.format ("%s (%.1f%%)", command, cpu))
end -- if
end -- if
end -- for loop
f:close()
-- if any over the limit, alert us
if #t > 0 then
os.execute ('zenity --title="CPU usage warning!" --info ' ..
'--text="These processes are using more than ' ..
THRESHOLD .. '% CPU:\n' ..
table.concat (t, ", ") ..
'" --ok-label="OK" ' ..
'--timeout=60 ' .. -- close dialog after one minute in case we aren't around
'--display=:0.0 ' -- ensure visible when running under cron
)
end -- if
Best Answer
You can use a modified version of this script to do what you want:
We're "CONNECTED" Example
With debugging turned on so you can see what the script's doing.
Running with a valid hostname to demonstrate the "connection is up" state.
The above initializes a couple of variables and determines the last time we went through the loop,
$lastAccessTime
. We now try to ping Google.We now calculate any down time,
$downTime
, if ping fails, otherwise, we reset$downTime
to zero, and recalculate$lastAccessTime
.Now we wait 15 seconds.
Now we check if we've been down for > 5 minutes (300 seconds). Then we repeat going through the
while
loop.As long as we're up, nothing will happen other than we check with the
ping
command every 15 seconds.We're "DISCONNECTED" Example
Now to simulate a "connection is down" state, we'll swap out the hostname we're pinging and use a fake one,
google1234567890.com
. Repeating a run of our script with debugging enabled we now see some actual down time getting calculated.Notice above that
$downTime
is equal to 15 seconds so far. If we wait a while longer we'll see this:We've accrued 300 seconds of down time. So now when we check, we print the message,
alert
.This state will continue until the connection is restored and the
ping
is once again successful.So what about a sound?
That's easy. You can use a variety of tools to do this. I would use something like
sox
ormplayer
to play an audio file such as an.mp3
or.wav
file with an appropriate sound you want to hear every 15 seconds, while the connection is down.Simply replace the
alert
message above with this line to get audio feedback that the connection is down.Timing out issues with ping
If you use
ping
in the manner above you'll likely encounter a slow lag time where it takesping
literally 10-20 seconds for it to fail when the connection is down. See my answer to this U&L Q&A titled: How to redirect the output of any command? for an example using the command line toolfing
instead. This tool will fail more quickly than the traditionalping
.