saurabh.hirani has asked for the wisdom of the Perl Monks concerning the following question:
Hey all,
I am writing a daemon in perl which will check for load average, free disk space on a particular partition and free memory and send it as an updation query to another daemon.
I am supposed to check for these params at least twice in a minute. I was looking at perl modules which would give me this info - but after looking under their hood - most of them fire system command to launch a shell. Some of them do it via /proc which I would rather do myself. My queries are
1. What is faster - reading /proc/loadavg or uptime? I would say /proc/loadavg.
2. Are there any perl modules which are using XS to get these queries done faster without opening a shell?
3. Load average I can get through /proc/loadavg, free memory through /proc/meminfo. But how to obtain free disk space through proc? I am talking about 2.6.x kernels on RHEL4. I want to use /proc as much as I can because I would be reading from a file and not launching a shell.
Are there any other suggestions that you guys think would be useful in writing such daemons which do frequent updates?
Thanks for going through my post.
regards,
Saurabh.
Re: get system info using perl
by moritz (Cardinal) on Feb 05, 2009 at 12:20 UTC
|
I think the speed differences can be neglected. When running time uptime and time cat /proc/uptime the variations are much larger than the difference between the respective execution times.
But why do you want to re-invent the wheel? There are tools like Nagios and collectd (which supports perl plugins) that can be used to obtain and collect such data. | [reply] [d/l] [select] |
Re: get system info using perl
by zentara (Archbishop) on Feb 05, 2009 at 15:26 UTC
|
If you want to save the spawning time of a new shell, you can keep a shell open in a pipe, using IPC::Open3, and send your commands to it. Put the command to-check in a while loop
#!/usr/bin/perl
use warnings;
use strict;
use IPC::Open3;
$|=1;
#my $pid=open3(\*IN,\*OUT,\*ERR,'/bin/bash');
my $pid=open3(\*IN,\*OUT,0,'/bin/bash');
# set \*ERR to 0 to send STDERR to STDOUT
my $cmd = 'date';
#send cmd to bash
print IN "$cmd\n";
my $result = <OUT>;
print $result;
like you I thought about making it more efficient by reading the file driectly. What I did, was find an assembly version of "cat", and did something like
sub refresh {
my $pid = shift;
#asmutils version of cat
my @size = split "\n", `/home/zentara/perl5lib/cat /proc/$pid/stat
+us`;
#my @size = split "\n", `cat /proc/$pid/status`;
(my $vmsize) = grep { /VmSize/ } @size;
my (undef, $size) = split ' ', $vmsize;
$t->configure(-text => "PID: $pid -> $size");
if ($size eq '') { exit }
}
}
I never really accurately tested which one is fastest, but the assembly cat version made me feel fast. :-)
| [reply] [d/l] [select] |
|
Thanks guys for your replies. I got a reply from comp.lang.perl.misc which pointed out the following 2 modules:
1.Filesys::Df
2. Linux::Sysinfo
They are pretty easy to use, fast, and provide many values. I know that my daemon is not going to bomb the other one once in a second. But I just wanted to know.
These modules really do pump up the speed from okay to burn-the-road. Just to compare system call and Filesys::Df, I wrote a small perl program which calls getting free disk using system call to df and using the module. I profiled them by running them around 1000 times and this was
the output of dprofpp:
Forking df and getting the time:
Total Elapsed Time = 42.04899 Seconds
User+System Time = 5.668994 Seconds
Inclusive Times
%Time ExclSec CumulS #Calls sec/call Csec/c Name
96.7 5.485 5.485 1000 0.0055 0.0055
main::get_freequeue
Using df from the module
Total Elapsed Time = 0.618107 Seconds
User+System Time = 0.768107 Seconds
Inclusive Times
%Time ExclSec CumulS #Calls sec/call Csec/c Name
92.1 0.013 0.708 1000 0.0000 0.0007
main::get_freequeue
90.4 0.013 0.695 1000 0.0000 0.0007 Filesys::Df::df
88.7 0.682 0.682 1000 0.0007 0.0007
Filesys::Df::_df
The difference is staggering.
I will also play around with the IPC mod as pointed ou by zentara. Looks interesting
| [reply] |
Re: get system info using perl
by slacker (Friar) on Feb 05, 2009 at 12:34 UTC
|
Regarding the third question.
I did some reading on this.
I do not believe there is a way, accessing only /proc, to obtain disk usage or space available.
I'd use system() with df -h to get a human readable output of all drive/partition information.
| [reply] |
Re: get system info using perl
by zwon (Abbot) on Feb 05, 2009 at 18:33 UTC
|
while(1) {
open my $la, '<', '/proc/loadavg';
print <$la>;
close $la;
sleep 1;
}
Upd: script fixed
| [reply] [d/l] |
Re: get system info using perl
by mr_mischief (Monsignor) on Feb 10, 2009 at 18:50 UTC
|
Rather than a hard-wired system you write yourself, you might want to get familiar with Net-SNMP. Using NetSNMP you can monitor a the local host OS, remote OSes, routers, switches, firewalls, and much more. You can then wrap around that in Perl with, for example, Net::SNMP.
As for a place to monitor the monitoring, there's always Mon, nagios, or Big Brother. There's also Argus, which is written in Perl itself and has a plugin module system.
I used to monitor DNS, SMTP, POP3, IMAP, RADIUS, HTTP, MySQL, and more servers for their server protocols, memory usage, disk usage, processor load, temperature, and network throughput with this combination. I also used Argus to monitor dozens of routers, switches, firewalls, and ISDN/dialup access concentrators that had their own SNMP implementations that came with them.
Argus can be configured to email you when very particular circumstances happen (like after a router interface shows down once on its 5-minute test, it'll test every 30 seconds until it's back up and email you if it's not up within 7 minutes of showing down). It handles a dependency tree so that it doesn't test devices it can't reach because of a failure in the middle.
Doing the work in Perl is a good thing, because Perl is well-suited to this kind of project. Since there's already a good solution written in Perl, perhaps you should take a look at it before reinventing this particular wheel. | [reply] |
|
|