[Orca-checkins] r293 - trunk/orca/data_gatherers/aix
Blair Zajac
blair at orcaware.com
Thu Apr 1 15:48:09 PST 2004
Author: blair
Date: Thu Apr 1 15:47:50 2004
New Revision: 293
Added:
trunk/orca/data_gatherers/aix/
trunk/orca/data_gatherers/aix/orca-aix-stat.pl (contents, props changed)
Log:
Add an aix data_gatherers directory and an AIX data collector.
* data_gatherers/aix:
New directory.
* data_gatherers/aix/orca-aix-stat.pl:
Initial import of orca-aix-stat.pl submitted by Rajesh Verma
<rajesh.verma at palmettohealth.org>.
Added: trunk/orca/data_gatherers/aix/orca-aix-stat.pl
==============================================================================
--- (empty file)
+++ trunk/orca/data_gatherers/aix/orca-aix-stat.pl Thu Apr 1 15:47:50 2004
@@ -0,0 +1,554 @@
+#!/usr/bin/perl
+#
+# Version 1.7
+
+# Description:
+# Collect general perfromance statistics formatted for
+# interpretaion by Orca.
+
+# Usage:
+# The following variables may be set:
+#
+# OUT_ROOT root directory for datafiles (eg /opt/log/performance)
+# INTERVAL the number of seconds between checks (eg 300 = 5 min)
+# DURATION numer of hours to run (eg 1 = 1 hr)
+#
+# This script runs various standard system utilities to collect
+# system performance statistics and writes them out to datafile named
+# HOSTNAME/stats.YYYY-MM-DD-HHmm under the OUT_ROOT directory.
+#
+# It runs for the the numbers specified by DURATION collecting data
+# every INTERVAL number of seconds. After DURATION, the script
+# closes and compresses it's datafile via /usr/bin/compress and then
+# exits. If DURATION=24 and INTERVAL=300 (recommended) then the
+# following cron entry would collect continuos stats for a system:
+#
+# 0 0 * * * /<PATH_TO_SCRIPT>/orca-aix-stat.pl
+#
+# 2003-09-10 - RV - Modified for AIX 4.3/5.x.. by Rajesh Verma
+# (rajeshverma at aixdude.com)
+# v1.7 - RV - ignores /proc now
+# 2001-04-16 - JDK - Genesis... by Jason D. Kelleher
+# 2001-05-02 - JDK - Updates to make data aggregation easier.
+# Added #open connections, pagestotl.
+# 2001-07-06 - JDK - added command-line args & data checks
+# 2001-07-09 - JDK - added signal handler, column checks, & umask
+# 2001-07-10 - JDK - now autodetects interfaces via netstat -i
+# v1.5
+#
+# $HeadURL$
+# $LastChangedDate$
+# $LastChangedBy$
+# $LastChangedRevision$
+
+# Note: Execution speed is more important than cleanliness here.
+
+# Explicitly set PATH to prevent odd problems if run manually.
+$ENV{PATH} = '/usr/bin:/etc:/usr/sbin:/usr/ucb:/sbin';
+
+$Usage_Message = '
+Usage: orca-aix-stat.pl [-r out_root] [-i interval] [-d duration] [-h]
+
+-r out_root set root output directory, default: /opt/log/performance
+-i interval number of seconds between checks, default: 300
+-d duration number of hours to run, default: 24
+-h this message
+
+';
+############################
+# These are the packages you need to install
+# 1. perl
+# 2. openssh - if using ssh to the collector server
+# 3. openssl
+# 4. zlib
+# 5. rsync - To copy file to the collector server
+# 6. gzip - to zip the files
+# 7. rpm.rte - to install rpm tools
+#
+# This the site you can file everything
+# http://www-1.ibm.com/servers/aix/products/aixos/linux/download.html
+# http://www.bullfreeware.com
+#
+#
+# Good Luck, Rajesh Verma (rajeshverma at yahoo.com)
+##############################
+
+# Parse the command line arguments
+while ( $#ARGV >= 0 ) {
+
+ if ( $ARGV[0] eq "-r" ) {
+ shift @ARGV;
+ $OUT_ROOT = shift @ARGV;
+ }
+ elsif ( $ARGV[0] eq "-i" ) {
+ shift @ARGV;
+ $INTERVAL = shift @ARGV;
+ }
+ elsif ( $ARGV[0] eq "-d" ) {
+ shift @ARGV;
+ $DURATION = shift @ARGV;
+ }
+ elsif ( $ARGV[0] eq "-h" ) {
+ print $Usage_Message;
+ exit 0;
+ }
+ elsif ( $ARGV[0] =~ /^-/ ) {
+ die "Invalid flag: $ARGV[0]\n$Usage_Message";
+ }
+ else {
+ die "Invalid argument: $ARGV[0]\n$Usage_Message";
+ }
+}
+
+## BEGIN set defaults
+
+$OUT_ROOT ||= '/home/orca/orcallator'; # root directory for datafiles
+$INTERVAL ||= 300; # seconds between checks
+$DURATION ||= 24; # number of hours to run
+
+## END set defaults
+
+## Derived variables.
+$iterations = $DURATION * 60 * 60 / $INTERVAL; # Number of checks.
+chomp( $HOST = `uname -n` );
+$out_dir = "${OUT_ROOT}/${HOST}";
+( $sec, $min, $hour, $mday, $mon, $year, $wday, $yday, $isdst ) =
+ localtime(time);
+$stat_file =
+ sprintf( "%s/percol-%.2d-%.2d-%.2d-%1d%.2d", $out_dir, $year + 1900, $mon + 1,
+ $mday, $hour, $min );
+
+# Base all timestamps on start time.
+$start_time = time();
+$timestamp = 0;
+
+## Autodetect network interfaces
+#open IN, "ifconfig -a|";
+open IN, "netstat -ni|";
+while (<IN>) {
+
+ # if ( /^(\S+):/ ) {
+ if (/^(\w+).*link/) {
+ push @net_interfaces, $1;
+ }
+}
+close IN;
+
+# Grab some base system info prior to collecting stats.
+open IN, "lsattr -El sys0 -a realmem |";
+while (<IN>) {
+ if (/^realmem (\d+) /) {
+ $pagestotl = $1 * 1024 / 4096; # Grab realmem in KB and convert to pages.
+ $mem_totl = $1 * 1024; # Grab realmem in KB and convert to Bytes.
+
+ # this gets used down in the vmstat section
+ }
+}
+close IN;
+
+## Make sure we can write output.
+umask 0022; # make sure the file can be harvested
+unless ( -d $out_dir ) {
+ system( "mkdir", "-p", "$out_dir" );
+}
+open OUT, ">$stat_file" or die "ERROR: Could not open $stat_file: $!";
+my $oldfh = select OUT;
+$| = 1;
+select $oldfh;
+
+# Set signal handlers to close and compress the output
+# file just in case.
+$SIG{HUP} = \&exit_nicely;
+$SIG{INT} = \&exit_nicely;
+$SIG{QUIT} = \&exit_nicely;
+$SIG{TERM} = \&exit_nicely;
+
+# Set gloabals used for printing (or not) headers.
+$need_header = 1;
+$prev_header_cnt = 0;
+$prev_info_cnt = 0;
+
+while ( $iterations-- > 0 ) {
+
+ $timestamp = $timestamp ? time() : $start_time;
+ ( $sec, $min, $hour, $mday, $mon, $year, $wday, $yday, $isdst ) =
+ localtime(time);
+ $locltime = sprintf( "%.2d:%.2d:%.2d", $hour, $min, $sec );
+
+ ## Get runq data
+ ## Get runq data
+ $uptime = 0;
+ open IN, "uptime |";
+ while (<IN>) {
+ if (/load average:\s+(\S+),\s+(\S+),\s+(\S+)/) {
+ $load_info = join "\t", $1, $2, $3;
+ }
+ @upt = split(/ +/,);
+ $uptd = $upt[3];
+ $nusr = $upt[6];
+ $up_day = $uptd * 24 * 60 * 60;
+ if (/days,\s+(\S+):(\S+), /) {
+ $up_hrs = $1 * 60 * 60;
+ $up_min = $2 * 60;
+ }
+ $uptime = $up_day + $up_hrs + $up_min;
+ }
+ close IN;
+ $load_header = "1runq\t5runq\t15runq";
+ $up_header = "uptime\tnusr";
+ $up_info = "$uptime\t$nusr";
+
+ if ( scalar( split ' ', $load_header ) != scalar( split ' ', $load_info ) )
+ {
+ $load_header = '';
+ $load_info = '';
+ $need_header = 1;
+ print STDERR "WARNING: load header does not match load info.\n";
+ }
+ if ( scalar( split ' ', $up_header ) != scalar( split ' ', $up_info ) )
+ {
+ $up_header = '';
+ $up_info = '';
+ $need_header = 1;
+ print STDERR "WARNING: UP header does not match load info.\n";
+ }
+
+
+ ## Get number of system processes
+ $num_proc = -1; # Don't count the header.
+ open IN, "ps -ek |";
+ while (<IN>) {
+ $num_proc++;
+ }
+ close IN;
+ $proc_info = $num_proc;
+ $proc_header = '#proc';
+
+ if ( scalar( split ' ', $proc_header ) != scalar( split ' ', $proc_info ) )
+ {
+ $proc_header = '';
+ $proc_info = '';
+ $need_header = 1;
+ print STDERR "WARNING: #proc header does not match #proc info.\n";
+ }
+
+ ## Get pstat data for pages
+ $sw_used = 0;
+ $sw_free = 0;
+ open IN, "pstat -s |tail -3 |";
+ while (<IN>) {
+ @swp = split(/ +/,);
+ if (/\d/) {
+ $sw_used = $swp[1];
+ $sw_free = $swp[2];
+ $swap_used = $sw_used * 4096;
+ $swap_free = $sw_free * 4096;
+ }
+ }
+ close IN;
+ $swap_info = "$swap_used\t$swap_free";
+ $swap_header = "\tswap_used\tswap_free";
+
+ if ( scalar( split ' ', $swap_header ) !=
+ scalar( split ' ', $swap_info ) )
+ {
+ print STDERR "WARNING: pstat header does not match pstat info.\n";
+ $swap_header = '';
+ $swap_info = '';
+ $need_header = 1;
+ }
+
+
+
+ ## Get vmstat data
+ open IN, "vmstat 1 2|";
+ while (<IN>) {
+ chomp;
+ if (/^[\s\d]+$/) {
+
+ # overwrite first line on 2nd pass
+ (
+ $vmstat_r, $vmstat_b, $vmstat_avm, $vmstat_fre,
+ $vmstat_re, $vmstat_pi, $vmstat_po, $vmstat_fr,
+ $vmstat_sr, $vmstat_cy, $vmstat_inf, $vmstat_syf,
+ $vmstat_csf, $vmstat_us, $vmstat_sy, $vmstat_id,
+ $vmstat_wa )
+ = split;
+ $vmstat_info = join "\t", $vmstat_r, $vmstat_b, $vmstat_avm,
+ $vmstat_fre, $pagestotl, $vmstat_pi, $vmstat_po, $vmstat_fr,
+ $vmstat_sr, $vmstat_us, $vmstat_sy, $vmstat_wa, $vmstat_id;
+ }
+ }
+ close IN;
+ $vmstat_header =
+"runque\twaiting\tpagesactive\tpagesfree\tpagestotl\tPagesI/s\tPagesO/s\tPagesF/s\tscanrate\tusr%\tsys%\twio%\tidle%";
+
+ if ( scalar( split ' ', $vmstat_header ) !=
+ scalar( split ' ', $vmstat_info ) )
+ {
+ print STDERR "WARNING: vmstat header does not match vmstat info.\n";
+ $vmstat_header = '';
+ $vmstat_info = '';
+ $need_header = 1;
+ }
+
+ ## Get filesystem data
+ $fs_header = '';
+ $fs_info = '';
+ open IN, "df -k -v |";
+ while (<IN>) {
+ chomp;
+
+ if (m%^/dev%) {
+ ( $mnt_dev, $blocks, $used, $free, $pct_used, $iused, $ifree,
+ $ipct_used, $mnt ) = split;
+
+ # Recalculate percents because df rounds.
+ $fs_info .= "\t"
+ . sprintf( "%s\t%s\t%s\t%.5f\t%d\t%s\t%s\t%.5f", $blocks, $used,
+ $free, ( $used / $blocks ) * 100, ( $iused + $ifree ), $iused,
+ $ifree, ( $iused / ( $iused + $ifree ) ) * 100 );
+ $fs_header .= "\t" . join "\t", "mntC_$mnt", "mntU_$mnt",
+ "mntA_$mnt", "mntP_$mnt", "mntc_$mnt", "mntu_$mnt", "mnta_$mnt",
+ "mntp_$mnt";
+ }
+ }
+ close IN;
+
+ if ( scalar( split ' ', $fs_header ) != scalar( split ' ', $fs_info ) ) {
+ print STDERR
+ "WARNING: filesystem header does not match filesystem info.\n";
+ $fs_header = '';
+ $fs_info = '';
+ $need_header = 1;
+ }
+
+ ## Get iostat data
+ $disk_t = 0;
+ $disk_rK = 0;
+ $disk_wK = 0;
+ undef %disks;
+ open IN, "iostat -d 1 2|";
+
+ while (<IN>) {
+ if (/^(\S+)\s+\S+\s+\S+\s+(\S+)\s+(\d+)\s+(\d+)/) {
+ my $disk = $1;
+ my $tps = $2;
+ my $rK = $3;
+ my $wK = $4;
+ if ( not $disks{$disk} ) {
+ $disks{$disk}++; # Get rK & wK from first pass.
+ $disk_rK += $rK;
+ $disk_wK += $wK;
+ }
+ else {
+ $disk_t += $tps; # Get trans per sec from second pass.
+ }
+ }
+ }
+ close IN;
+ $iostat_header = "disk_t/s\tdisk_rK/s\tdisk_wK/s";
+ $iostat_info = "${disk_t}\t${disk_rK}\t${disk_wK}";
+
+ if ( scalar( split ' ', $iostat_header ) !=
+ scalar( split ' ', $iostat_info ) )
+ {
+ print STDERR "WARNING: iostat header does not match iostat info.\n";
+ $iostat_header = '';
+ $iostat_info = '';
+ $need_header = 1;
+ }
+
+ ## Get packet data
+ $packet_header = '';
+ $packet_info = '';
+
+ #foreach $interface ( split(/\s+/, $NET_INTERFACES) ) {
+ foreach $interface (@net_interfaces) {
+ $packet_header .=
+"\t${interface}Ipkt/s\t${interface}IErr/s\t${interface}Opkt/s\t${interface}OErr/s\t${interface}Coll/s\t";
+ open IN, "netstat -n -I $interface 1|";
+
+ while (<IN>) {
+ if (/^\s*(\d+)\s+(\d+)\s+(\d+)\s+(\d+)\s+(\d+)\s+/) {
+ $packet_info .= "\t" . join "\t", $1, $2, $3, $4, $5;
+ last;
+ }
+ }
+ close IN;
+ }
+
+ if ( scalar( split ' ', $packet_header ) !=
+ scalar( split ' ', $packet_info ) )
+ {
+ print STDERR "WARNING: packet header does not match packet info.\n";
+ $packet_header = '';
+ $packet_info = '';
+ $need_header = 1;
+ }
+
+ ## Get TCP Connection data
+ $tcp_estb = 0;
+ open IN, "netstat -an |";
+ while (<IN>) {
+ if (/^tcp.+ESTABLISHED$/) {
+ $tcp_estb++;
+ }
+ }
+ close IN;
+ $tcp_info = $tcp_estb;
+ $tcp_header = 'tcp_estb';
+
+ if ( scalar( split ' ', $tcp_estb_header ) !=
+ scalar( split ' ', $tcp_estb_info ) )
+ {
+ print STDERR "WARNING: tcp_estb header does not match tcp_estb info.\n";
+ $tcp_estb_header = '';
+ $tcp_estb_info = '';
+ $need_header = 1;
+ }
+
+ ## Get TSM Database space usage
+ $tsmdb = 0;
+ open IN, "dsmadmc -id=view -password=view 'query db' |tail -r -n 5 |";
+ while (<IN>) {
+ @fld = split(/ +/,);
+ if (/\d/) {
+ $tsmdb = $fld[8];
+ }
+ }
+ close IN;
+ $tsm_info = $tsmdb;
+ $tsm_header = "tsmdb\t";
+
+ if ( scalar( split ' ', $tsm_header ) !=
+ scalar( split ' ', $tsm_info ) )
+ {
+ print STDERR "WARNING: tsmdb header does not match tsmdb info.\n";
+ $tsm_header = '';
+ $tsm_info = '';
+ $need_header = 1;
+ }
+
+ ## Get Memory Usage breakup using SVMON
+ $mem_work = 0;
+ $mem_pres = 0;
+ $mem_clnt = 0;
+ open IN, "svmon -G |tail -2 |";
+ while (<IN>) {
+ @memp = split(/ +/,);
+ if (/use\s+(\d+) /) {
+ $m_work = $memp[2];
+ $m_pres = $memp[3];
+ $m_clnt = $memp[4];
+ $mem_work = $m_work * 4096;
+ $mem_pres = $m_pres * 4096;
+ $mem_clnt = $m_clnt * 4096;
+ }
+ }
+ close IN;
+ $mem_info = "$mem_work\t$mem_pres\t$mem_clnt\t$mem_totl";
+ $mem_header = "mem_work\tmem_pres\tmem_clnt\tmem_totl";
+
+ if ( scalar( split ' ', $mem_header ) !=
+ scalar( split ' ', $mem_info ) )
+ {
+ print STDERR "WARNING: memory header does not match memory info.\n";
+ $mem_header = '';
+ $mem_info = '';
+ $need_header = 1;
+ }
+
+ ## Get TSM Tape Drive usage
+ $rmt = 0;
+ $rmt5 = 5;
+ open IN, "dsmadmc -id=view -password=view 'query mount' |grep matches |";
+ while (<IN>) {
+ @fld = split(/ +/,);
+ if (/\d/) {
+ $rmt = $fld[1];
+ }
+ }
+ close IN;
+ $tsm_rmt_header = "rmt5\trmt\t";
+ $tsm_rmt_info = "$rmt5\t$rmt";
+
+ if ( scalar( split ' ', $tsm_rmt_header ) !=
+ scalar( split ' ', $tsm_rmt_info ) )
+ {
+ print STDERR "WARNING: TSM RMT header does not match TSM RMT info.\n";
+ $tsm_rmt_header = '';
+ $tsm_rmt_info = '';
+ $need_header = 1;
+ }
+
+ ## Get TSM Recovery Log space usage
+ $tsmdb = 0;
+ open IN, "dsmadmc -id=view -password=view 'query log' |tail -r -n 4 |";
+ while (<IN>) {
+ @fld = split(/ +/,);
+ if (/\d/) {
+ $tsmlog = $fld[8];
+ }
+ }
+ close IN;
+ $tsm_log_info = $tsmlog;
+ $tsm_log_header = 'tsmlog';
+
+ if ( scalar( split ' ', $tsm_log_header ) !=
+ scalar( split ' ', $tsm_log_info ) )
+ {
+ print STDERR "WARNING: TSM Log header does not match TSM Log info.\n";
+ $tsm_log_header = '';
+ $tsm_log_info = '';
+ $need_header = 1;
+ }
+
+ ## Join header and info then verify column counts.
+ $out_header = join "\t", "timestamp", "locltime", $load_header, $up_header,
+ $proc_header, $vmstat_header, $fs_header, $iostat_header, $packet_header,
+ $tcp_header, $tsm_header, $swap_header, $mem_header, $tsm_rmt_header;
+ $out_header =~ tr/ \t/\t/s; # translate whitespace to single tabs
+
+ $out_info = join "\t", $timestamp, $locltime, $load_info, $up_info, $proc_info,
+ $vmstat_info, $fs_info, $iostat_info, $packet_info, $tcp_info, $tsm_info,
+ $swap_info, $mem_info, $tsm_rmt_info;
+ $out_info =~ tr/ \t/\t/s; # translate whitespace to single tabs
+
+ $header_cnt = split ' ', $out_header;
+ $info_cnt = split ' ', $out_info;
+ if ( $header_cnt != $info_cnt ) {
+ print STDERR
+ "ERROR: header columns do not equal data columns. Exiting.\n";
+ &exit_nicely;
+ }
+ elsif ( $header_cnt != $prev_header_cnt or $info_cnt != $prev_info_cnt ) {
+ $need_header = 1;
+ }
+ $prev_header_cnt = $header_cnt;
+ $prev_info_cnt = $info_cnt;
+
+ ## Write output
+ if ($need_header) {
+ print OUT $out_header, "\n";
+ $need_header = 0;
+ }
+ print OUT $out_info, "\n";
+
+ sleep $INTERVAL - ( time() - $timestamp );
+
+}
+close OUT;
+
+ at args = ( "/usr/bin/gzip", "-f", "$stat_file" );
+system(@args);
+
+exit 0;
+
+# This subroutine is called by the signal handler.
+sub exit_nicely {
+ close OUT;
+ @args = ( "/usr/bin/gzip", "-f", "$stat_file" );
+ system(@args);
+ exit 0;
+}
More information about the Orca-checkins
mailing list