#!/usr/bin/perl -w # ----------------------------------------------------------------- # System Information Script for the X-Chat IRC client # (http://www.xchat.org/) # # Credits: # This script is based on whoo's hacked up sysinfo script v.0.2.8 # Avaliable at http://www.owenmeany.com/linux.html # Author: # The original script credits: # Xwild, for making me fix the dual processor bugs # sys_rage, for being my conscious, and a most tolerant teacher, # considering how damn bitchy I can be # and elfing, for throwing perl books at my feet # Bargraph for memory via mIRC style is courtesy of # Sebastian Wenzler # Fix for traffic/in traffic/out not just showing in Gbytes is # courtesy of caetin # # Then we credit: # Gabriel Devenyi to include apm battery status 22/11/01 # # And now me: # Toby Oxborrow http://www.oxborrow.net/ # What I've changed (Since Tue Feb 12 21:59:31 GMT 2002): # # Indenting (tabs, 8 chars wide as the good saint linus teaches us) # Let us "use strict" please # Reworked almost compleatly under Gabriels orders :D # Reimplimented apm support # Turn awk into native perl regexp's # Stop using system greps and use perl loops # Reworked the commenting # chomp instead of chop # cat /proc/meminfo instead of using 'free' # changed 'df' to 'df -l -P'. # Added uptime, users, load and apm # Added lmsensors support to report ambient and cpu temperature # Added iffy Sparc/PPC CPU support # Added colour (or not, via $COLOUR) # Some of the output (eg cpu details, lmsensors, apm) wont be displayed if that information isnt available # # Thanks to the guys and gals in #humour on irc.dhbit.ca who # tested it and found more bugs to fix. # # ----------------------------------------------------------------- # COPYLEFT # ----------------------------------------------------------------- # This program is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License # as published by the Free Software Foundation; either version 2 # of the License, or any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. # For more on the GPL please visit: http://www.gnu.org/copyleft/gpl.html # # ----------------------------------------------------------------- # USAGE # ----------------------------------------------------------------- # /sys # The /sys command displays a hefty chunk of system information # /net # This command displays network status # /up # Displays uptime, users, load # use strict; # ----------------------------------------------------------------- # CONFIGURATION # ----------------------------------------------------------------- my $DEV = 'ppp0'; # Device to query for "/net" command # If you are on a lan, eth0 should do # If you use a dial-up modem, ppp0 is most likely my $COLOUR = 1; # To use colour or to not use colour. # BTW I'm British, it is spelt with a U, get over it. # that is all you need to change. # # xchat intergration # IRC::register('Sysinfo', '0.3.2', '', ''); IRC::print('Loading lord slapmonkey\'s sysinfo script (/sys, /net or /up)'); IRC::add_command_handler('sys', 'displaySysInfo'); IRC::add_command_handler('net', 'displayNet'); IRC::add_command_handler('up', 'displayUptime'); # # some constants # my $GIG = 1024**3; # bytes in a gig my $MEG = 1024**2; # bytes in a meg # # user called methods # sub displaySysInfo() { # output to channel my $uname = &getOS(); my ($cpu_model, $cpu_mhz, $cpu_bogos, $cpus) = &getCPU(); my $procs = &getProcs(); my ($mem_used, $mem_total, $mem_bar) = &getMem(); my ($disk_used, $disk_total, $disk_bar) = &getDisk(); my $screen_res = &getScreen(); my ($net_in, $net_out) = &getNet(); my ($uptime, $users, $load) = &getUptimeUsersLoad(); my $apm = &getAPM(); my ($ambient_temp, $cpu_temp, $sbr_temp) = &getTemps(); my $output = "SysInfo: $uname"; if ($cpu_model) { $output .= " | $cpu_model"; } if (($cpu_model) && ($cpu_mhz)) { $output .= " \@ $cpu_mhz" . 'MHz'; } if ($cpus == 2) { $output .= ' (Dual CPUs)'; } elsif ($cpus > 2) { $output .= " ($cpus CPUs)"; } if ($cpu_bogos) { $output .= " | BogoMIPS: $cpu_bogos"; } $output .= " | Mem: $mem_used/$mem_total $mem_bar | Diskspace: $disk_used/$disk_total $disk_bar | Screen Res: $screen_res | Procs: $procs | "; $output .= "$DEV: In: $net_in Out: $net_out | Uptime: $uptime | Users: $users | Load: $load"; if ($apm) { $output .= " | Battery: $apm"; } if ($ambient_temp) { $output .= " | Temperature: Ambient: $ambient_temp CPU: $cpu_temp"; } IRC::command("/say $output"); return 1; } sub displayNet() { my @temp = &getNet(); IRC::command("/say Network stats: In: $temp[0] Out: $temp[1]"); return 1; } sub displayUptime() { my ($uptime, $users, $load) = &getUptimeUsersLoad(); IRC::command("/say Uptime: $uptime | Users: $users | Load: $load"); return 1; } # # info gathering methods # sub getNet() { my @dev_info; foreach my $line (`cat /proc/net/dev`) { if ($line =~ m/$DEV:(.*)$/o) { @dev_info = split(' ', $1); last; } } return (&byteFormatter($dev_info[0]), &byteFormatter($dev_info[8])); } sub getOS() { # OS platform my $uname = `uname -sr`; chomp $uname; return $uname; } sub getCPU() { # cpu information my ($cpu_model, $cpu_mhz, $cpu_bogos, $cpus); foreach my $line (`cat /proc/cpuinfo`) { if ($line =~ m/^model name\s+:\s+(.*)$/o) { $cpu_model = $1; } elsif ($line =~ m/^cpu\s+:\s+(.*)$/o) { $cpu_model = $1; $cpus++; } # sparc uses this elsif ($line =~ m/^cpu MHz\s+:\s+(.*)$/o) { $cpu_mhz = sprintf("%.0f", $1); } elsif ($line =~ m/^bogomips\s+:\s+(.*)$/io) { $cpu_bogos = $1; } elsif ($line =~ m/^processor/o) { $cpus++; } } # try and get a bit more info if it is not ix86 based my $unamem = `uname -m`; if ($unamem !~ m/i\d86/o) { if ($unamem eq 'sparc') { $unamem = 'Sparc'; } # pretty capital s if (($unamem eq 'Sparc') || ($unamem eq 'PPC')) { if ($cpu_model) { $cpu_model = "$unamem $cpu_model"; } else { my $unamep = `uname -p`; if (($unamep) && ($unamep ne 'unknown')) { $cpu_model = "$unamem $unamep"; } else { $cpu_model = $unamem; } } } } return (&cleanSpaces($cpu_model), &cleanSpaces($cpu_mhz), &cleanSpaces($cpu_bogos), $cpus); } sub getProcs() { # number of processes running my $procs; foreach (`ps ax`) { $procs++; } $procs -= 2; # ignore heading line and the 'ps ax' command itself return $procs; } sub getMem() { # memory stats my ($mem_total, $mem_free, $mem_used, $mem_pused, $mem_buffers, $mem_cached); foreach my $line (`cat /proc/meminfo`) { if ($line =~ m/^MemTotal:.*?(\d+)/o) { $mem_total = $1; } elsif ($line =~ m/^MemFree:.*?(\d+)/o) { $mem_free = $1; } elsif ($line =~ m/^Buffers:.*?(\d+)/o) { $mem_buffers = $1; } elsif ($line =~ m/^Cached:.*?(\d+)/o) { $mem_cached = $1; } } $mem_used = ($mem_total - $mem_free) - ($mem_buffers + $mem_cached); $mem_pused = ($mem_used * 100) / $mem_total; $mem_pused = sprintf("%.0f", $mem_pused); my $mem_bar = &makeBar($mem_pused); $mem_total /= 1000; $mem_total = sprintf("%.0fMB", $mem_total); $mem_used /= 1000; $mem_used = sprintf("%.0fMB", $mem_used); return ($mem_used, $mem_total, $mem_bar); } sub getScreen() { # screen resolution my $screen_res; foreach my $line (`xdpyinfo`) { if ($line =~ m/dimensions:.*?(\S+) /o) { $screen_res = $1; chomp $screen_res; last; } } return $screen_res; } sub getDisk() { # diskspace my (@df_info, @df_cols, $disk_total, $disk_free, $disk_used, $disk_pused); # -P will print out on one line only # This helps when you have a device like /dev/ide/host0/bus0/target0/lun0/part5 # As I did (until I made replaced its fstab entry with a neater symlink) @df_info = split("\n", `df -l -P`); shift @df_info; # ignore the heading foreach my $line (@df_info) { my @df_cols = split(' ', $line); $disk_total += $df_cols[1]; $disk_free += $df_cols[3]; } $disk_used = ($disk_total - $disk_free); $disk_pused = ($disk_used * 100) / $disk_total; $disk_pused = sprintf("%.0f", $disk_pused); my $disk_bar = &makeBar($disk_pused); return (&kbyteFormatter($disk_used), &kbyteFormatter($disk_total), $disk_bar); } sub getUptimeUsersLoad() { #1:28pm up 11 days, 11:52, 2 users, load average: 2.00, 2.00, 2.00 #4:23pm up 50 min, 2 users, load average: 0.35, 0.33, 0.13 my ($uptime, $users, $load); $uptime = `uptime`; $uptime =~ m/up\s+(.*),\s+(.*?) users?,.*:\s+(.*)/o; $uptime = $1; $users = $2; $load = $3; # when it's in hh:mm format, change to be more readable $uptime =~ s/:(\d\d)/ hours $1 minutes/o; # $uptime =~ s/mins/minutes/o; # lets not look stupid $uptime =~ s/^1 hours/1 hour/o; $uptime =~ s/ 1 minutes$/1 minute/o; # colour the load # idealy, the 'normal' 'in use' level is the same as how many cpus you have # however the values below do not take this into account, they simply assume 1 cpu. my @temp = split(', ', $load); $temp[0] = &colour($temp[0], 2, 4, 6) . $temp[0] . &endColour(); $temp[1] = &colour($temp[1], 2, 4, 6) . $temp[1] . &endColour(); $temp[2] = &colour($temp[2], 2, 4, 6) . $temp[2] . &endColour(); $load = "$temp[0], $temp[1], $temp[2]"; return ($uptime, $users, $load); } sub getAPM() { my ($apm); $apm = `apm`; $apm =~ m/:\s+(.*?)$/o; return ($1); } sub getTemps() { my ($ambient_temp, $cpu_temp, $sbr_temp, $chip_set, @tmp); $chip_set = "it87-isa-0290"; ($tmp[0],$tmp[1],$ambient_temp) = split(/ /,(`cat /proc/sys/dev/sensors/$chip_set/temp2`)); ($tmp[0],$tmp[1],$cpu_temp) = split(/ /,(`cat /proc/sys/dev/sensors/$chip_set/temp1`)); if ($ambient_temp) { $ambient_temp =~ m/^(\D*)(\d+)(.*)$/o; $ambient_temp = &colour($2, 30, 50, 70) . "$1$2$3" . &endColour(); } if ($cpu_temp) { $cpu_temp =~ m/^(\D*)(\d+)(.*)$/o; $cpu_temp = &colour($2, 30, 50, 70) . "$1$2$3" . &endColour(); } return ($ambient_temp, $cpu_temp); } # # output formatters # takes byte or kbyte input, returns the value in GB's or MB's # sub byteFormatter() { my $temp = $_[0]; if ($temp >= $GIG) { $temp = sprintf("%.1fGB", $temp / $GIG); } else { $temp = sprintf("%.1fMB", $temp / $MEG); } return $temp; } sub kbyteFormatter() { my $temp = $_[0]; if (($temp * 1000) >= $GIG) { $temp /= 1000**2; $temp = sprintf("%.0fGB", $temp); } else { $temp /= 1000**3; $temp = sprintf("%.0fMB", $temp); } return $temp; } # # Useful little methods # # Returns a colour code based on an input value and some ranges. # $value = The value to test # $r1, $r2, $r3 = The ranges to compare $value against sub colour() { if (!$COLOUR) { return; } my ($value, $r1, $r2, $r3) = @_; if ($value >= $r3) { return '04'; } # red bold elsif ($value >= $r2) { return '04'; } # red elsif ($value >= $r1) { return '07'; } # orange return ''; } # Returns the code to end colour sub endColour() { if (!$COLOUR) { return; } return ''; } # removes double, leading and trailing spaces sub cleanSpaces() { my $temp = $_[0]; while ($temp =~ m/ /o) { $temp =~ s/ / /o; } $temp =~ s/^ | $//o; return $temp; } sub makeBar() { my $value = int($_[0] / 10); my $temp; if ($COLOUR) { $temp = '7['; if ($value == 10) { $temp .= '4' } # red bold if full elsif ($value >= 8) { $temp .= '4'; } # red is high else { $temp .= '3'; } # otherwise green $temp .= '|'x$value . '14' . '-'x(10-$value) . '7]'; } else { $temp = '[' . '|'x$value . '-'x(10-$value) . ']'; } return $temp; }