#!/usr/bin/perl -w # # collector for /proc statistics for use with Linux 2.2 and 2.4 kernels. # # Copyright (C) 2001 Guilherme Carvalho Chehab. All Rights Reserved. # # Config variables $PROC="/proc"; # Proc directory, usually /proc $INTERVAL=60; # Interval between each measure, in seconds $HOSTNAME=`/bin/hostname`; chomp $HOSTNAME; $DEST_DIR="/var/orca/rrd"; # Destination dir for output files # Initializations $r=0; # Rotating indice for measuring counter differences $rate_ok=0; # Check if is ok to calculate rates # Create output dir if needed if (! -d $DEST_DIR ) { `mkdir -p $DEST_DIR`; } # Read kernel version open (F_VERSION, "<$PROC/version"); #($os,$line,$version)=split / +/ , , 4; ($os,$line,$dumb)=split / +/ , , 4; close (F_VERSION); # Main loop do { # Loop initializations $n_cols[$r]=0; # Get Local time & uptime $timestamp=time(); ($sec,$min,$hour,$mday,$mon,$year,$yday,$isdst)=localtime($timestamp); $mon+=1; $year+=1900; $locltime=sprintf "%02d:%02d:%02d", $hour,$min,$sec; open (F_UPTIME,"<$PROC/uptime"); ($uptime)=split / +/,; close (F_UPTIME); # insert in output table put_output("timestamp",$timestamp,"locltime",$locltime,"uptime",$uptime); # Evaluate filename $out_filename[$r]=sprintf "%s/$HOSTNAME-%04d-%02d-%02d",$DEST_DIR, $year,$mon,$mday; # Read load average open (F_LOADAVG, "<$PROC/loadavg"); ($runq_1, $runq_5, $runq_15, $proc_run, $procs[$r], $last_pid)=split / +|\//, ; chomp $last_pid; close (F_LOADAVG); put_output ( "1runq",$runq_1, "5runq",$runq_5, "15runq",$runq_15, "#proc_oncpu",$proc_run, "#proc",$procs[$r], "#proc/s",rate(@procs) ); # Read system stats open (F_STAT, "<$PROC/stat"); $n_cpus=0; while ( $line= ) { chomp ($line); if ( $line=~/cpu[0-9]*/ ) { ($cpu[$r][$n_cpus], $usr[$r][$n_cpus], $nice[$r][$n_cpus], $sys[$r][$n_cpus], $idle[$r][$n_cpus])= split / +/,$line; $total[$r][$n_cpus]= $usr[$r][$n_cpus] + $nice[$r][$n_cpus] + $sys[$r][$n_cpus] + $idle[$r][$n_cpus]; $n_cpus++; } if ( $line=~/ctxt/) { ($dumb, $ctxt[$r])= split / +/,$line; } if ( $line=~/intr/) { @dumb=split / /,$line; $intr[$r]=0; $i=1; while ($i<@dumb) { $intr[$r]+=$dumb[$i]; $i++; } } } close (F_STAT); # Operate percentuals and rates for system Stats for ($i=0;$i<$n_cpus ;$i++) { $usr_100 [$i]=rate_prcnt($usr [$r][$i],$usr [1-$r][$i],$total[$r][$i],$total[1-$r][$i]); $nice_100[$i]=rate_prcnt($nice[$r][$i],$nice[1-$r][$i],$total[$r][$i],$total[1-$r][$i]); $sys_100 [$i]=rate_prcnt($sys [$r][$i],$sys [1-$r][$i],$total[$r][$i],$total[1-$r][$i]); $idle_100[$i]=rate_prcnt($idle[$r][$i],$idle[1-$r][$i],$total[$r][$i],$total[1-$r][$i]); if ($i==0) { put_output("ncpus",$n_cpus-1,"usr%",$usr_100 [$i],"nice%",$nice_100[$i],"sys%",$sys_100 [$i],"wait%",$idle_100[$i]); } else { if ($n_cpus>2) { put_output("usr_%_$i",$usr_100 [$i],"nice_%_$i",$nice_100[$i],"sys_%_$i",$sys_100 [$i],"wait_%_$i",$idle_100[$i]); } } } # Read Uptime open (F_STAT, "<$PROC/uptime"); $line=; close (F_STAT); chomp ($line); ($uptime, $idletime) = split / +/,$line; put_output ( "uptime",($uptime/3600/24), "idletime",($idletime/3600/24) ); # Get bytes in/out $line = `iptables -vnx -L INPUT | grep ACCEPT`; chomp $line; ($dumb, $dumb, $dumb, $dumb, $dumb, $dumb, $bytes, $dumb) = split / +/,$line; put_output ( "#b_in",$bytes); $line = `iptables -vnx -L OUTPUT | grep ACCEPT`; chomp $line; ($dumb, $dumb, $dumb, $dumb, $dumb, $dumb, $bytes, $dumb) = split / +/,$line; put_output ( "#b_out",$bytes); # Read Virtual Memory stats open (F_STAT, "<$PROC/vmstat"); while ( $line= ) { chomp ($line); if ( $line=~/pgpgin/) { ($dumb, $page_in[$r])= split / +/,$line; } if ( $line=~/pgpgout/) { ($dumb, $page_out[$r])= split / +/,$line; } if ( $line=~/pswpin/) { ($dumb, $swap_in[$r])= split / +/,$line; } if ( $line=~/pswpout/) { ($dumb, $swap_out[$r])= split / +/,$line; } } close (F_STAT); put_output ( "pages_in",rate(@page_in), "pages_out",rate(@page_out), "swap_in",rate(@swap_in), "swap_out",rate(@swap_out), "ctxt/s",rate(@ctxt), "intr/s",rate (@intr) ); # Read Disk I/O report @dsk=0; $i=0; ($dsk_stat_t[$r],$dsk_rio_t[$r],$dsk_rblk_t[$r],$dsk_wio_t[$r],$dsk_wblk_t[$r])=(0,0,0,0); open (F_STAT, "<$PROC/diskstats"); while ( $line= ) { chomp ($line); @dsk= split / +/,$line; $dsk_maj[$r][$i] = $dsk[1]; $dsk_min[$r][$i] = $dsk[2]; $dsk_name[$r][$i] = $dsk[3]; $dsk_rio[$r][$i] = $dsk[4]; $dsk_rblk[$r][$i] = $dsk[5]; $dsk_wio[$r][$i] = $dsk[6]; $dsk_wblk[$r][$i] = $dsk[7]; # Only pick /dev/md# and /dev/sda & sdb if ( ($dsk_maj[$r][$i] == 9) || ( ($dsk_maj[$r][$i] == 8) && ( ($dsk_min[$r][$i] == 0) || ($dsk_min[$r][$i] == 16) ) ) ) { $i++; } } close (F_STAT); $n_dsk = $i; for ($i=0; $i<$n_dsk; $i++) { $dsk_stat_t[$r] += 0; $dsk_rio_t[$r] += $dsk_rio[$r][$i]; $dsk_rblk_t[$r] += $dsk_rblk[$r][$i]; $dsk_wio_t[$r] += $dsk_wio[$r][$i]; $dsk_wblk_t[$r] += $dsk_wblk[$r][$i]; } put_output ( "disk_op/s",rate(@dsk_stat_t), "disk_rd/s",rate(@dsk_rio_t), "disk_wr/s",rate(@dsk_wio_t), "disk_rB/s",rate(@dsk_rblk_t), "disk_wB/s",rate(@dsk_wblk_t) ); for ($i=0; $i<$n_dsk; $i++) { # $dumb="c$dsk_maj[$r][$i]_d$dsk_min[$r][$i]"; put_output("disk_op_$dsk_name[$r][$i]/s",rate($dsk_stat[$r][$i],$dsk_stat[1-$r][$i]), "disk_rd_$dsk_name[$r][$i]/s",rate($dsk_rio[$r][$i], $dsk_rio[1-$r][$i]), "disk_wr_$dsk_name[$r][$i]/s",rate($dsk_wio[$r][$i], $dsk_wio[1-$r][$i]), "disk_rB_$dsk_name[$r][$i]/s",rate($dsk_rblk[$r][$i],$dsk_rblk[1-$r][$i]), "disk_wB_$dsk_name[$r][$i]/s",rate($dsk_wblk[$r][$i],$dsk_wblk[1-$r][$i]) ); } # Get number of httpd instances $httpd = `ps -ef | grep httpd | grep -v grep | wc -l`; chomp $httpd; $httpd =~ s/^\s+//; put_output ( "#httpd", $httpd); # Get number of mysql instances $mysqld = `ps -ef | grep mysqld | grep -v grep | wc -l`; chomp $mysqld; $mysqld =~ s/^\s+//; put_output ( "#mysqld", $mysqld); # Get number of sshd instances $sshd = `ps -ef | grep sshd | grep -v grep | wc -l`; chomp $sshd; $sshd =~ s/^\s+//; put_output ( "#sshd", $sshd); # Get hardware sensors data @sensors=`/usr/local/bin/sensors`; ($dumb, $vcore1) = split / +/,$sensors[2]; ($dumb, $vcore2) = split / +/,$sensors[3]; ($dumb, $v3_3) = split / +/,$sensors[4]; ($dumb, $v5) = split / +/,$sensors[5]; ($dumb, $v12) = split / +/,$sensors[6]; ($dumb, $cpufan) = split / +/,$sensors[7]; ($dumb, $cputemp) = split / +/,$sensors[8]; ($dumb, $mbtemp1) = split / +/,$sensors[9]; ($dumb, $mbtemp2) = split / +/,$sensors[10]; put_output ( "vcore1",$vcore1, "vcore2",$vcore2, "v3_3V",$v3_3, "v5V",$v5, "v12V",$v12, "cpu_fan",$cpufan, "cpu_temp",$cputemp, "mb_temp1",$mbtemp1, "mb_temp2",$mbtemp2 ); # Get filesystem ocupation @df=`/bin/df -k`; for ($i=1,$j=0;$df[$i];$i++) { if (!(($df[$i]=~/cdrom/)||($df[$i]=~/cdrom/))) { chomp $df[$i]; ($dumb, $fs[2][$j], $fs[3][$j], $dumb, $dumb, $fs[0][$j])= split / +/,$df[$i]; $fs[1][$j]=prcnt($fs[3][$j],$fs[2][$j]); put_output("mnt_$fs[0][$j]",$fs[1][$j]); $j++; } } $n_fs=$j; # Get memory ocupation open (F_MEMINFO, "<$PROC/meminfo"); while ( $line= ) { chomp ($line); if ( $line=~/MemTotal:/) { ($dumb, $mem_total, $dumb)= split / +/,$line; } if ( $line=~/MemFree:/) { ($dumb, $mem_free, $dumb)= split / +/,$line; } if ( $line=~/Buffers:/) { ($dumb, $mem_buff, $dumb)= split / +/,$line; } if ( $line=~/Cached:/) { ($dumb, $mem_cchd, $dumb)= split / +/,$line; } $mem_shrd = 0; if ( $line=~/SwapTotal:/) { ($dumb, $swp_total, $dumb)= split / +/,$line; } if ( $line=~/SwapFree:/) { ($dumb, $swp_free, $dumb)= split / +/,$line; } } close (F_MEMINFO); put_output ( "mem_used%",prcnt(($mem_total-$mem_free),$mem_total), "mem_free%",prcnt($mem_free,$mem_total), "mem_shrd%",prcnt($mem_shrd,$mem_total), "mem_buff%",prcnt($mem_buff,$mem_total), "mem_cchd%",prcnt($mem_cchd,$mem_total), "swp_free%",prcnt($swp_free,$swp_total), "swp_used%",prcnt(($swp_total-$swp_free),$swp_total) ); # Get network interface statistics open (F_NET_DEV, "<$PROC/net/dev"); $i=0; while ($line=) { if ($line=~/:/) { ($if_name[$i][$r],$line)=split /: */,$line; ($dumb, $if_name[$i][$r])=split /^ +/,$if_name[$i][$r]; ( $if_in_b[$i][$r], $if_in_p[$i][$r], $if_in_e[$i][$r], $if_in_d[$i][$r], $if_in_ff[$i][$r], $if_in_fr[$i][$r], $if_in_c[$i][$r], $if_in_m[$i][$r], $if_out_b[$i][$r], $if_out_p[$i][$r], $if_out_e[$i][$r], $if_out_d[$i][$r], $if_out_ff[$i][$r],$if_out_cl[$i][$r], $if_out_ca[$i][$r], $if_out_cp[$i][$r] ) = split / +/,$line; put_output ( "if_in_b_$if_name[$i][$r]", rate ($if_in_b[$i][$r] ,$if_in_b[$i][1-$r]), "if_in_p_$if_name[$i][$r]", rate ($if_in_p[$i][$r],$if_in_p[$i][1-$r]), "if_in_e_$if_name[$i][$r]", rate ($if_in_e[$i][$r],$if_in_e[$i][1-$r]), "if_in_d_$if_name[$i][$r]", rate ($if_in_d[$i][$r],$if_in_d[$i][1-$r]), "if_in_ff_$if_name[$i][$r]", rate ($if_in_ff[$i][$r],$if_in_ff[$i][1-$r]), "if_in_fr_$if_name[$i][$r]", rate ($if_in_fr[$i][$r],$if_in_fr[$i][1-$r]), "if_in_c_$if_name[$i][$r]", rate ($if_in_c[$i][$r],$if_in_c[$i][1-$r]), "if_in_m_$if_name[$i][$r]", rate ($if_in_m[$i][$r],$if_in_m[$i][1-$r]), "if_out_b_$if_name[$i][$r]", rate ($if_out_b[$i][$r],$if_out_b[$i][1-$r]), "if_out_p_$if_name[$i][$r]", rate ($if_out_p[$i][$r],$if_out_p[$i][1-$r]), "if_out_e_$if_name[$i][$r]", rate ($if_out_e[$i][$r],$if_out_e[$i][1-$r]), "if_out_d_$if_name[$i][$r]", rate ($if_out_d[$i][$r],$if_out_d[$i][1-$r]), "if_out_ff_$if_name[$i][$r]",rate ($if_out_ff[$i][$r],$if_out_ff[$i][1-$r]), "if_out_cl_$if_name[$i][$r]",rate ($if_out_cl[$i][$r],$if_out_cl[$i][1-$r]), "if_out_ca_$if_name[$i][$r]",rate ($if_out_ca[$i][$r],$if_out_ca[$i][1-$r]), "if_out_cp_$if_name[$i][$r]",rate ($if_out_cp[$i][$r],$if_out_cp[$i][1-$r]) ); $i++; } } $n_nets=$i; # Get TCP/IP statistics open (F_SNMP, "<$PROC/net/snmp"); $j=0; while ($line=) { $line2=; chomp $line; chomp $line2; ($cat,$line) = split /: +/,$line; ($dumb,$line2)=split /: +/,$line2; (@dumb) =split / +/,$line; (@dumb2)=split / +/,$line2; for ($i=0; $dumb[$i]; $i++, $j++) { $net_parm[0][$j]=sprintf "%s_%s",$cat,$dumb[$i]; $net_parm[2+$r][$j]= $dumb2[$i]; $net_parm[1][$j]= rate ($net_parm[2+$r][$j],$net_parm[3-$r][$j]); SWITCH: { if ($cat=~/Ip/) { if ($net_parm[0][$j]=~/In|Out|Forw|Reasm|Frag/) { put_output("$net_parm[0][$j]",$net_parm[1][$j]); }; last SWITCH; } if ($cat=~/Icmp/) { put_output("$net_parm[0][$j]",$net_parm[1][$j]); last SWITCH; } if ($cat=~/Udp/) { put_output("$net_parm[0][$j]",$net_parm[1][$j]); last SWITCH; } if ($cat=~/Tcp/) { if ($net_parm[0][$j]=~/Rto|Max/) { last SWITCH; } if ($net_parm[0][$j]=~/CurrEstab/) { put_output("g$net_parm[0][$j]",$net_parm[2+$r][$j]); last SWITCH; } put_output("$net_parm[0][$j]",$net_parm[1][$j]); last SWITCH; }; } } } $net_parms=$j; # flush output flush_output(); $r=1-$r; $rate_ok=1; # Wait for the next INTERVAL sleep ($INTERVAL-time() % $INTERVAL); } while (1); # to perl dont complain on unused vars ($os,$n_fs,$net_parms,$n_nets,$cpu,$yday,$isdst)=($os,$n_fs,$net_parms,$n_nets,$cpu,$yday,$isdst); sub rate { my ($a,$b) = @_; my $c; $c= (!($a&&$b))?0:((abs($a-$b)%$INTERVAL)==0)?abs($a-$b)/$INTERVAL:sprintf("%.3f",abs($a-$b)/$INTERVAL); return $c; } sub prcnt { my ($a,$b) = @_; return ($b==0) ? 0 : sprintf ("%.2f",100 * $a / $b); } sub rate_prcnt { my ($a1,$a2,$b1,$b2) = @_; if (!($a1&&$b1&&$a2&&$b2)) { return 0; } return (abs($b1-$b2)==0)?0:sprintf ("%.2f",100*abs($a1-$a2)/abs($b1-$b2)); } sub flush_output { my $t; # check if new file is not required open (F_OUT,">>$out_filename[$r]") or die "Could not open output"; if (!$rate_ok) { for ($t=0;$t<$n_cols[$r];$t++) { print F_OUT $out [0][$t]," "; } print F_OUT "\n"; } else { if ( ($n_cols[$r]!=$n_cols[1-$r]) || ($out_filename[$r] ne $out_filename[1-$r]) || $rate_ok==0 ) { for ($t=0;$t<$n_cols[$r];$t++) { print F_OUT $out [0][$t]," "; } print F_OUT "\n"; } } for ($t=0;$t<$n_cols[$r];$t++) { print F_OUT $out [1][$t]," "; } print F_OUT "\n"; close F_OUT; @out=(); } sub put_output { my (@a) = @_; my $t; for ($t=0;$a[$t];$t+=2,$n_cols[$r]+=1) { $out [0][$n_cols[$r]]=$a[$t]; $out [1][$n_cols[$r]]=$a[$t+1]; } }