I wondered how to monitor load on my GNU/Linux boxen. Sure, there are a lot of canned apps out there. But what if I wanted to use Perl? (IUD SIS, you must use Perl, cuz Perl’s the best… Readin’ from my Camel book like you wanted me… script the pain away…) Anyhoo… I wanna use Perl. I want to trigger events based on the current load and track the previous load state. The first reaction is to search for a module, right? Well, if you are monitoring GNU/Linux boxen, there is a very simple way to get load stats using the proc filesystem. Enough! Let’s see some code:
%servers= ( srv-33 => "super", srv-3 => "ok", srv-44 => "messed up", srv-34 => "thanks for asking", ); for $server (keys %servers){ print $server," - ",$servers{$server},"\n"; } |
The above script sets up a hash of server names with text values. The cool thing about using a hash is that the server name can be used as a friendly name in the output of the script. Here is the output of the above script:
srv-34 - thanks for asking srv-44 - messed up srv-3 - ok srv-33 - super |
One quick and dirty way to get load stats is to cat /proc/loadavg. I’ve set up keys to the other servers I’m monitoring, so I can grab the remote load stats by:
[root@ares simplestats]# ssh root@srv-33 "cat /proc/loadavg" 0.03 0.04 0.24 1/26 6618 [root@ares simplestats]# |
Let’s add this to the script:
%servers= ( srv-33 => "super", srv-3 => "ok", srv-44 => "messed up", srv-34 => "thanks for asking", ares => "super", ); for $server (keys %servers){ @ss=split " ",`ssh root\@$server "cat /proc/loadavg"`; print $server," - old status:",$servers{$server},"\n"; print "Current Load: ",$ss[0]," ",$ss[1]," ",$ss[2],"\n"; } |
One tricky part of the above script is using the backticks around the ssh command so that it will assign the output to a string. The output of the above script:
srv-34 - old status:thanks for asking Current Load: 0.08 0.03 0.00 ares - old status:super Current Load: 0.15 0.12 0.09 srv-44 - old status:messed up Current Load: 0.01 0.00 0.00 srv-3 - old status:ok Current Load: 0.24 0.05 0.02 srv-33 - old status:super Current Load: 0.15 0.03 0.01 |
If we want to trigger on certain conditions, we could use this script:
%servers= ( srv-33 => "super", srv-3 => "ok", srv-44 => "messed up", srv-34 => "thanks for asking", ares => "super", ); for $server (keys %servers){ @ss=split " ",`ssh root\@$server "cat /proc/loadavg"`; print $server," - old status:",$servers{$server},"\n"; print "Current Load: ",$ss[0]," ",$ss[1]," ",$ss[2],"\n"; if ($ss[0] == 0.00){ $servers{$server}="super"; } elsif ($ss[0] < 0.03){ $servers{$server}="ok"; } elsif ($ss[0] < 0.11){ $servers{$server}="thanks for asking"; } else { $servers{$server}="messed up"; } print $server," - new status:",$servers{$server},"\n"; } |
The output looks like this:
srv-34 - old status:thanks for asking Current Load: 0.00 0.00 0.00 srv-34 - new status:super ares - old status:super Current Load: 0.14 0.08 0.03 ares - new status:messed up srv-44 - old status:messed up Current Load: 0.00 0.00 0.00 srv-44 - new status:super srv-3 - old status:ok Current Load: 0.07 0.02 0.00 srv-3 - new status:thanks for asking srv-33 - old status:super Current Load: 0.13 0.03 0.01 srv-33 - new status:messed up |
Of course, you could do anything you want based on the load. If you are monitoring a pool of servers, you could route new connections to other boxes if the load gets too high, etc.