#!/usr/bin/perl ############################################################################### #### systory.client #### $Id: systory.client,v 1.17 2004/04/25 00:25:12 ssklar Exp $ ############################################################################### use strict; use Socket; my ($version) = ('$Revision: 1.17 $ ' =~ /^\$\w+: (.*) \$ $/); ############################################################################### #### $sys is defined based on the OS of the system the script is running on. #### Its value corresponds to a "package" by the same name found at the bottom #### of this script, whose contents is a sub called "gather_data". my $sys; BEGIN { if ( $^O =~ /aix/ ) { $sys = 'aix' } elsif ( $^O =~ /sol/ ) { $sys = 'solaris' } elsif ( $^O =~ /lin/ ) { $sys = 'linux' } elsif ( $^O =~ /dar/ ) { $sys = 'macosx' } else { die "unknown operating system.\n" } }; ############################################################################### #### look for a file named "/nosystory" or "/etc/nosystory"; if it exists, #### silently exit... if ( ( -f "/nosystory" ) || ( -f "/etc/nosystory" ) ) { exit 0 }; #### check the value of $ARGV[0]; if it is "debug" (or empty), dump the output #### to STDOUT. Otherwise, split it into a server name and port to which we #### will send the data. my ($debug, $server, $port); if ((scalar @ARGV == 0) || ($ARGV[0] =~ /debug/i )) { $debug++; } elsif ($ARGV[0] =~ /version/i) { print STDERR "$0: version $version\n"; exit 0; } else { if ($ARGV[0] =~ /(^\w+.*):(\d+$)/) { ($server, $port) = ($1, $2) } elsif ($ARGV[0] =~ /^\w+$/ && $ARGV[1] =~ /^\d+$/) { ($server, $port) = ($ARGV[0], $ARGV[1]) } else { die "Usage:\n$0 server:port -or-\n$0 server port -or-\n$0 debug\n\n" }; }; #### The following variables will be populated by calling the "gather_data" #### subrouting in the appropriate package. my (@cmd, $os, $os_vers, $hostid, $hostname, $model, $ram, $serial, $num_proc, $proc_speed, $swap_used, $uptime, $cpu_user, $cpu_system, $load_01, $load_05, $load_15); $sys->gather_data; #### The hash "%d" contains the keys and values that will be sent to the #### systory server. my %d; $d{'time'} = time(); $d{'client_vers'} = $version; $d{'os'} = &get_os; $d{'os_vers'} = &get_os_vers; $d{'hostid'} = &get_hostid; $d{'hostname'} = &get_hostname; $d{'model'} = &get_model; $d{'ram'} = &get_ram; $d{'serial'} = &get_serial; $d{'num_proc'} = &get_num_proc; $d{'proc_speed'} = &get_proc_speed; $d{'swap_used'} = &get_swap_used; $d{'uptime'} = &get_uptime; @d{'upsecs', 'upsecs_match'} = &get_upsecs; @d{'cpu_user', 'cpu_system'} = &get_cpu_usage; @d{'load_01', 'load_05', 'load_15'} = &get_load; ############################################################################### if ($debug) { foreach (sort keys %d) { printf "%-20s%-s\n", $_, $d{$_} }; } else { my $iaddr = inet_aton($server); my $paddr = sockaddr_in($port, $iaddr); my $proto = getprotobyname('tcp'); socket (SERVER, PF_INET, SOCK_STREAM, $proto) || die "socket: $!"; connect (SERVER, $paddr) || die "connect: $!"; foreach (keys %d) { print SERVER ("$_" . "|" . "$d{$_}\n") }; close (SERVER) || die "close: $!"; }; exit 0; ############################################################################### sub get_os { return ($os || "UNDEF") }; sub get_os_vers { return ($os_vers || "UNDEF") }; sub get_hostid { return ($hostid || "UNDEF") }; sub get_hostname { return ($hostname || "UNDEF") }; sub get_model { return ($model || "UNDEF") }; sub get_ram { return ($ram || "UNDEF") }; sub get_serial { return ($serial || "UNDEF") }; sub get_num_proc { return ($num_proc || "UNDEF") }; sub get_proc_speed { return ($proc_speed || "UNDEF") }; sub get_uptime { return ($uptime || "UNDEF") }; #### for the following vars, "0" is a legal value, so we have to check for #### definedness ... sub get_swap_used { return (defined ($swap_used) ? $swap_used : "UNDEF") }; sub get_cpu_usage { return (defined ($cpu_user) ? $cpu_user : "UNDEF"), (defined ($cpu_system) ? $cpu_system : "UNDEF") }; sub get_load { return (defined ($load_01) ? $load_01 : "UNDEF"), (defined ($load_05) ? $load_05 : "UNDEF"), (defined ($load_15) ? $load_15 : "UNDEF") }; #### this subroutine converts the string returned by "get_uptime" to seconds sub get_upsecs { my $days = 60 * 60 * 24; my $hours = 60 * 60; my $mins = 60; # return "UNDEF" unless exists ($d{'uptime'}); if ($d{'uptime'} =~ /\s+(\d+)\s+day\(?s?\)?,?\s+(\d+):(\d+),/) { return ($1 * $days) + ($2 * $hours) + ($3 * $mins), "1" } elsif ($d{'uptime'} =~ /(\d+)\s+day\(?s?\)?,?\s+(\d+)\s*min/ ) { return ($1 * $days ) + ($2 * $mins), "2" } elsif ($d{'uptime'} =~ /(\d+)\s+day\(?s?\)?,?\s+(\d+)\s*h/ ) { return ($1 * $days) + ($2 * $hours), "3" } elsif ($d{'uptime'} =~ /(\d+)\s+day\(?s?\)?,?\s+(\d+):(\d+)/ ) { return ($1 * $days) + ($2 * $hours) + ($3 * $mins), "4" } elsif ($d{'uptime'} =~ /(\d+)\s+day\(?s?\)?,?/ ) { return ($1 * $days), "5" } elsif ($d{'uptime'} =~ /(\d\d?):(\d\d)/ ) { return ($1 * $hours) + ($2 * $mins), "6" } elsif ($d{'uptime'} =~ /(\d\d?)\s+hr\(?s?\)?(,?\s+(\d+))?/ ) { return (($1 * $hours) + ((defined $2) ? $3 * $mins : 0)), "7" } elsif ($d{'uptime'} =~ /(\d\d?)\s+min/ ) { return ($1 * $mins), "8" } else { return "UNDEF", "9" } }; ############################################################################### package macosx; sub gather_data { #### $model, $num_proc, $ram, $serial ... @cmd = qw(/usr/sbin/system_profiler -detailLevel -2 SPHardwareDataType 2>/dev/null); open (CMD, "@cmd |") or die "Can't run @cmd: $!\n"; while () { next unless /:/; $model = $1 if /Model:\s(.*$)/; $num_proc = $1 if /CPUs:\s(\d+$)/; $proc_speed = $1 if /CPU Speed:\s(.*$)/; $serial = $1 if /Serial\sNumber:\s(\w+$)/; $ram = $1 * 1024 if /Memory:\s(\d+)/; }; close CMD; #### $os ... @cmd = qw(/usr/bin/sw_vers -productName 2>/dev/null); chomp ($os = `@cmd`); #### $os_vers ... @cmd = qw(/usr/bin/sw_vers -productVersion 2>/dev/null); chomp ($os_vers = `@cmd`); @cmd = qw(/usr/bin/sw_vers -buildVersion 2>/dev/null); chomp (my $build = `@cmd`); $os_vers .= " (" . $build . ")"; #### $hostname ... @cmd = qw(/bin/hostname -s 2>/dev/null); chomp ($hostname = `@cmd`); #### $uptime, $load_01, $load_05, $load_15 @cmd = qw(/usr/bin/uptime 2>/dev/null); if (`@cmd` =~ /up\s+(.*),\s+\d+.*:\s+(\d+.\d+),?\s+(\d+.\d+),?\s+(\d+.\d+)/) { ($uptime, $load_01, $load_05, $load_15) = ($1, $2, $3, $4) }; #### $cpu_user, $cpu_system ... @cmd = qw(/usr/sbin/iostat 1 1 2>/dev/null | /usr/bin/tail -1); if (`@cmd` =~ /(\d+)\s+(\d+)\s+\d+$/) { ($cpu_user, $cpu_system) = ($1, $2) }; }; 1; ## END package macosx ############################################################################### package aix; sub gather_data { #### $os ... @cmd = qw(/usr/bin/uname -s 2>/dev/null); chomp ($os = `@cmd`); #### $os_vers ... @cmd = qw(/usr/bin/oslevel -r 2>/dev/null); chomp ($os_vers = `@cmd`); #### $hostname ... @cmd = qw(/usr/bin/hostname -s 2>/dev/null); chomp ($hostname = `@cmd`); #### $uptime, $load_01, $load_05, $load_15 @cmd = qw(/usr/bin/uptime 2>/dev/null); if (`@cmd` =~ /up\s+(.*),\s+\d+.*:\s+(\d+.\d+),?\s+(\d+.\d+),?\s+(\d+.\d+)/) { ($uptime, $load_01, $load_05, $load_15) = ($1, $2, $3, $4) }; #### $hostid ... @cmd = qw(/usr/sbin/hostid 2>/dev/null); chomp ($hostid = `@cmd`); #### $model ... @cmd = qw(/usr/sbin/lsattr -El sys0 -a modelname 2>/dev/null); if (`@cmd` =~ /^modelname\s+(IBM,\d{4}-\w{3})/) { $model = $1 }; #### $ram ... @cmd = qw(/usr/sbin/lsattr -El sys0 -a realmem 2>/dev/null); if (`@cmd` =~ /^realmem\s+(\d+)/) { $ram = $1 / 1024 }; #### $serial ... @cmd = qw(/usr/sbin/lsattr -El sys0 -a systemid 2>/dev/null); if (`@cmd` =~ /^systemid\s+IBM,(\w+)\s+/) { $serial = $1 }; #### $num_proc ... @cmd = qw(/usr/sbin/lsdev -Cc processor -S Available 2>/dev/null); open (CMD, "@cmd |") or die "Can't run @cmd: $!\n"; while () { $num_proc++; }; close CMD; #### $proc_speed ... @cmd = qw(/usr/sbin/lsattr -El proc0 -a frequency 2>/dev/null); if (`@cmd` =~ /^frequency\s+(\d+)\s+/) { $proc_speed = int(($1/1000000) + .5) . " MHz" } else { @cmd = qw(/usr/sbin/lscfg -vpl sysplanar0 2>/dev/null); open (CMD, "@cmd |") or die "Can't run @cmd: $!\n"; while () { next unless /PS=(.*?),/; $proc_speed = int((oct("0x$1") / 1000000) + .5) . " MHz"; last; }; }; #### $cpu_user, $cpu_system ... @cmd = qw(/usr/bin/vmstat 1 2 2>/dev/null | /usr/bin/tail -1); if (`@cmd` =~ /(\d+)\s+(\d+)\s+\d+\s+\d+$/) { ($cpu_user, $cpu_system) = ($1, $2) }; #### $swap_used ... @cmd = qw(/usr/sbin/lsps -s 2>/dev/null | /usr/bin/tail -1); if (`@cmd` =~ /(\d+)%/) { $swap_used = $1 }; }; 1; ## END package aix ############################################################################### package solaris; sub gather_data { #### if we can find a "sysinfo" binary, we'll use that to gather some of #### the data needed ... my @bindirs = qw(/usr/local/bin /usr/bin /main/local/bin); my $sysinfo; foreach (@bindirs) { if ( -x "$_/sysinfo") { $sysinfo = "$_/sysinfo"; last }; }; if ($sysinfo =~ /sysinfo/) { @cmd = "$sysinfo -format report -class general 2> /dev/null"; open (CMD, "@cmd |") or die "Can't run @cmd: $!\n"; my @fields; while () { chomp; @fields = split (/\|\s+/, $_); #### $os, $os_vers, $model, $num_proc, $proc_speed ... $os = $fields[4] if $fields[2] =~ /osname/; $os_vers = $fields[4] if $fields[2] =~ /osvers/; $model = $fields[4] if $fields[2] =~ /model/; $num_proc = $fields[4] if $fields[2] =~ /numcpu/; $proc_speed = $fields[4] if $fields[2] =~ /cpuspeed/; }; }; #### sometimes, sysinfo doesn't give us the all the data that we want, or #### it segfaults due to an old version, or otherwise has problems. So ... unless ($os) { @cmd = qw(/usr/bin/uname -s 2>/dev/null); chomp ($os = `@cmd`); }; unless ($os_vers) { @cmd = qw(/usr/bin/uname -rv 2>/dev/null); chomp ($os_vers = `@cmd`); }; unless ($model) { @cmd = qw(/usr/bin/uname -i 2>/dev/null); chomp ($model = `@cmd`); }; unless ($proc_speed && $num_proc) { @cmd = qw(/usr/sbin/psrinfo -v 2> /dev/null); open (CMD, "@cmd |") or die "Can't run @cmd: $!\n"; $num_proc = "0"; while () { $num_proc++ if /^Status/; unless ($proc_speed) { $proc_speed = $1 . " MHz" if /operates\sat\s+(\d+)\s+/; }; }; close CMD; }; #### $hostname ... @cmd = qw(/usr/bin/hostname 2>/dev/null); ($hostname = `@cmd`) =~ s/(\w+)\..*/$1/; chomp $hostname; #### $uptime, $load_01, $load_05, $load_15 @cmd = qw(/usr/bin/uptime 2>/dev/null); if (`@cmd` =~ /up\s+(.*),\s+\d+.*:\s+(\d+.\d+),?\s+(\d+.\d+),?\s+(\d+.\d+)/) { ($uptime, $load_01, $load_05, $load_15) = ($1, $2, $3, $4) }; #### $cpu_user, $cpu_system ... @cmd = qw(/usr/bin/iostat 1 2 2>/dev/null | /usr/bin/tail -1); if (`@cmd` =~ /(\d+)\s+(\d+)\s+\d+\s+\d+$/) { ($cpu_user, $cpu_system) = ($1, $2) }; #### $hostid ... @cmd = qw(/usr/bin/hostid 2>/dev/null); chomp ($hostid = `@cmd`); #### $swap_used ... @cmd = qw(/usr/sbin/swap -s 2>/dev/null); if (`@cmd` =~ /=\s+(\d+)\w\sused,\s(\d+)/) { $swap_used = sprintf "%d", ( $1 / ($1 + $2) * 100 ) }; @cmd = qw(/usr/sbin/prtconf 2>/dev/null); open (CMD, "@cmd |") or die "Can't run @cmd: $!\n"; while () { $ram = $1 if /Memory size:\s+(\d*)/ }; close CMD; }; 1; ## END package solaris ############################################################################### package linux; sub gather_data { #### os ... @cmd = qw(/bin/uname -s 2>/dev/null); chomp ($os = `@cmd`); #### os_vers ... @cmd = qw(/bin/uname -r 2>/dev/null); chomp ($os_vers = `@cmd`); #### hostid ... @cmd = qw(/usr/bin/hostid 2>/dev/null); chomp ($hostid = `@cmd`); #### hostname ... @cmd = qw(/bin/hostname -s 2>/dev/null); chomp ($hostname = `@cmd`); #### model ... @cmd = qw(/bin/uname -i 2>/dev/null); chomp ($model = `@cmd`); #### num_proc, proc_speed ... open (FILE, "/proc/cpuinfo") or die "Can't open /proc/cpuinfo: $!\n"; while () { $num_proc++ if /^processor\s+:/; $proc_speed = sprintf ("%d MHz", $1) if /^cpu MHz\s+:\s+(.*)/; }; close FILE; #### ram, swap_used ... open (FILE, "/proc/meminfo") or die "Can't open /proc/meminfo: $!\n"; my ($swap_total, $swap_free); while () { $ram = sprintf ("%d", $1 / 1024) if /MemTotal:\s+(\d+)/; $swap_total = $1 if /SwapTotal:\s+(\d+)/; $swap_free = $1 if /SwapFree:\s+(\d+)/; }; close FILE; $swap_used = sprintf "%d", (($swap_total - $swap_free) / $swap_total * 100); #### $uptime, $load_01, $load_05, $load_15 @cmd = qw(/usr/bin/uptime 2>/dev/null); if (`@cmd` =~ /up\s+(.*),\s+\d+.*:\s+(\d+.\d+),?\s+(\d+.\d+),?\s+(\d+.\d+)/) { ($uptime, $load_01, $load_05, $load_15) = ($1, $2, $3, $4) }; #### cpu_user, cpu_system @cmd = qw(/usr/bin/vmstat 1 2 2>/dev/null | tail -1); if (`@cmd` =~ /(\d+)\s+(\d+)\s+\d+$/) { ($cpu_user, $cpu_system) = ($1, $2); }; }; 1; ## END package linux ###############################################################################