Perl is perfect for parsing the output of system programs and making sense of the data. Here's a some-what unorthodox example: parsing the output of sensors.
I use KDE, as my window manager. One (somewhat) useful KDE program I use is called 'superkaramba', it basically allows you to create little widgets that sit on your desktop and display useful information. One particular widget that I use displays hard disk partition sizes, network activity, RAM / SWAP usage, etc. It can also display the temperature or your CPU. That's mighty useful. It wasn't displaying anything about my CPU though.
I opened the config file for the widget and found a sed command that parsed a file which contained information about the CPU status. Only, I don't have that file, nor the utility which created it.
So here's what I did.
I installed a program called 'lm_sensors', which gives you a handy read-out with all kinds of information in it, including the CPU temperature, power supply temperature, cpu fan speed, etc. all pretty printed in your console.
All I needed to do was write a perl program to parse the output and give me the CPU temperature. But the project went a little bit further than that, as you can see below:
CAVEAT:
You must have 'lm_sensors' installed on your PC, and lm_sensors must be configured properly and running if you expect to get any out-put from this program ;)
NOTE:
... added logic to print help screen if no arguments are passed, per jesuashok ;)
#!/usr/bin/perl # s e n s o r s - e x t r a c t ---------------------- # author: Soup Nazi # version: 1.0.0 # description: parse the output of 'sensors' and # fetch what you want # t h i s m a c h i n e k i l l s f a s c i s t s - our $NAME = "sensors-extract"; our $VERSION = "1.0.0"; our $SCALE = "f"; my %args = @ARGV; print fetch_help() if !%args; my %cswt = ( -f => ["fetch_info", "\tFan.\n\tOptions:\tchassis, cpu, power.\ +n\tUsage:\t\t\$ ./sensor_utils.pl -f cpu\n"], -t => ["fetch_info", "\tTemperature.\n\tOptions:\tcpu, mb, powe +r.\n\tUsage:\t\t\$ ./sensor_utils.pl -t cpu\n"], -h => ["fetch_help", "\tHelp.\n\tPrint help dialog.\n\tUsage:\t +\t\$ ./$NAME -h\n"], ); my @cswt = keys %cswt; foreach my $key (keys %args) { # make sure we've been given valid command switches: if (!grep /$key/, @cswt) { print "Invalid argument: \"$key\".\nValid arguments:\n"; foreach my $arg (@cswt) { print "$arg $cswt{$arg}[1]"; } exit; } # good ... we have valid command switches, now to # run the prorgam and collect data: my $data = `sensors -$SCALE`; # remove -$SCALE for celsius { no strict 'refs'; print $cswt{$key}[0]($key, $args{$key}, $data); } } sub fetch_info { my ($type, $arg, $data) = @_; # valid arguments: my (@types, @valid); @types = qw(-f -t); @valid = qw(chassis cpu power) if $type eq $types[0]; @valid = qw(cpu mb power) if $type eq $types[1]; _sanity_check($arg, @valid); # good, now parse data according to use-case: my ($reg_ex1, $reg_ex2); ($reg_ex1 = "Chassis Fan:", $reg_ex2 = "\\(min") if $arg eq $vali +d[0] && $type eq $types[0]; ($reg_ex1 = "CPU Fan:", $reg_ex2 = "\\(min") if $arg eq $v +alid[1] && $type eq $types[0]; ($reg_ex1 = "Power Fan:", $reg_ex2 = "\\(min") if $arg eq $val +id[2] && $type eq $types[0]; ($reg_ex1 = "\\(AMD\\):", $reg_ex2 = "\\(high") if $arg eq $val +id[0] && $type eq $types[1]; ($reg_ex1 = "M/B Temp:", $reg_ex2 = "\\(high") if $arg eq $vali +d[1] && $type eq $types[1]; ($reg_ex1 = "Power Temp:", $reg_ex2 = "\\(high") if $arg eq $va +lid[2] && $type eq $types[1]; my ($junk, $outp) = split /$reg_ex1/, $data; my ($outp, $junk) = split /$reg_ex2/, $outp; $outp =~ s/^\s*//gsx; $outp =~ s/\s*$//gsx; return $outp; } sub fetch_help { my $help_msg =<<HELP; Welcome to $NAME version $VERSION! You may check the status (rpm, temperature) of several devices includi +ng: For fans: - chassis fan\t\t(-f chassis) - cpu fan\t\t(-f cpu) - power fan\t\t(-f power) For temperature: - cpu temperature\t(-t cpu) - mb temperature\t(-t mb) - power temperature\t(-t power) Usage: \$ ./$NAME -f chassis\t\t... for chassis fan speed \$ ./$NAME -t cpu\t\t... for cpu temperature etc... HELP } sub _sanity_check { my ($check, @valid) = @_; if (!grep /$check/, @valid){ print "Invalid argument:\t\"$check\"\nPlease use:\t\t\$ ./$NAM +E -h\n... for more information.\n"; exit; } }
... all I need to do is type:
and I get the temperature readout for my cpu$ /usr/sbin/sensors-extract -t cpu
... gives me the RPM's my power supply fan is spinning at.$ /usr/sbin/sensors-extract -f power
So I have the program all set up, and it works perfectly with my superkaramba desktop widget. I set the widget up so that it uses my program as the program, and it runs at 360000 millisecond intervals, putting the newest temperature right there along with my other CPU information.
But why stop there? With a little extra code, you can set the program up to write the temperature of your cpu, m/b, and power supply along with the time / date at regular intervals to a flat file database and track the information over a period of time to guage how well the circuits and things are holding up. Might be useful to over-clockers, who knows.
Anyway, enjoy, thanks for your time :-)
In reply to Parsing 'sensors' output by SoupNazi
| For: | Use: | ||
| & | & | ||
| < | < | ||
| > | > | ||
| [ | [ | ||
| ] | ] |