# $Header: emdprocesschars.pl 02-may-2007.03:02:07 bguhatha Exp $ # # emdprocesschars.pl # # Copyright (c) 2002, 2007, Oracle. All rights reserved. # # NAME # emdprocesschars.pl # # DESCRIPTION # Script that provides an API to get at certain characteristics of # a process P. # # NOTES # USAGE: emdprocesschars.pl # Where process_number is the process we want to look at # # MODIFIED (MM/DD/YY) # bguhatha 05/02/07 - Backport bguhatha_bug-5365614 from main # nsharma 02/01/07 - AIX bug 5257669 # nsharma 12/18/06 - Bug 5719319 on HP, remove obsoleted methods # cvaishna 04/04/07 - Bug Fix : 5694782 # cvaishna 04/10/07 - XbranchMerge cvaishna_bug-5694782 from main # kganapat 09/01/05 - Add getPIDS subroutine # sksaha 07/26/05 - Adding subroutine getThreadCount # aaitghez 04/25/05 - bug 3731255. pe code changes into main # aaitghez 11/04/04 - bug 3843569. PLE changes # aaitghez 03/24/04 - # aaitghez 03/19/04 - bug 3511020 # mbhoopat 03/10/04 - linux port # skumar 01/13/04 - 10G changes for emd procstats to exclude threads # rzkrishn 01/08/04 - having cmdresult as local # gachen 12/03/03 - 3292538 # njagathe 10/28/03 - Stop collecting uptime # aaitghez 05/13/03 - bug 2916669 # aaitghez 01/20/03 - bug 2755430 # klmichae 08/20/02 - fix warnings # aaitghez 08/26/02 - add getPhysicalMemoryUsagePerct # aaitghez 08/21/02 - let getFileHandles take list # aaitghez 07/16/02 - add no child capabilities # aaitghez 07/26/02 - don't examine this process while getting statistics # xxu 06/25/02 - remove /usr/local/bin/perl # aaitghez 06/24/02 - add number of threads held by child processes # vnukal 06/21/02 - Enumerate all procs in getFileHandles # aaitghez 06/13/02 - aaitghez_bug-2254629 # aaitghez 05/29/02 - Creation # $stat_offset=2; sub countFileHandlesOfType { (my $pid) = @_; $cmd = "ls -l /proc/$pid/fd | wc -l"; my $r = `$cmd` or warn "Could not execute $cmd: $!"; $r =~ s/\s//g; return $r; }#end countFileHandlesOfType ############################################ # getProcessCharsRec ( # , # , # , (includes pid and ppid cols) # , # , # , ############################################## my %commands = (); sub getProcessCharsRec { my $pid = shift(@_); my $include_children = shift(@_); my $num_cols = shift(@_); my $get_file_handles = shift(@_); my $resarray = shift(@_); my $ret_array = shift(@_); my $fields = shift(@_); my $size = 0; my $ignore = ''; my $numrows = @$resarray/$num_cols; ##print "NUM ROWS = $numrows - ".scalar(@$resarray)." - $num_cols\n"; my $row = 0; for($row = 0; $row < $numrows; $row++) { my $col; $parent_id = @$resarray[($num_cols*$row)]; $process_id = @$resarray[($num_cols*$row)+1]; if($process_id == $pid) { if ($include_children != 1 || $commands{$parent_id} ne $commands{$pid}) { #this process ##print "THIS PROCESS\n"; for($col = $stat_offset ; $col < $num_cols; $col++) { if ($^O eq "dec_osf") { if (@$fields[$col] eq "vsz" || @$fields[$col] eq "rss") { $size = @$resarray[($num_cols*$row)+$col]; if ($size =~ /K/) # KB { ($size, $ignore) = split('K', $size); } elsif ($size =~ /M/) # MB { ($size, $ignore) = split('M', $size); $size *= 1024; } elsif ($size =~ /G/) # GB { ($size, $ignore) = split('G', $size); $size *= 1024 * 1024; } @$resarray[($num_cols*$row)+$col] = $size; } } ##print "VALUE = @$resarray[($num_cols*$row)+$col]\n"; @$ret_array[$col-$stat_offset] = @$ret_array[$col-$stat_offset ] + @$resarray[($num_cols*$row)+$col]; if($get_file_handles == 1) { ##print "INCLUDE FILE HANDLES\n"; @$ret_array[$num_cols-$stat_offset] = countFileHandlesOfType($process_id); } } } } if($include_children == 1 && $parent_id == $pid) { #we want to loop for the kids ##print "KIDS".scalar(@$resarray)."\n"; getProcessCharsRec($process_id, $include_children, $num_cols, $get_file_handles, \@$resarray, \@$ret_array, \@$fields); } } } ######################################### # getProcessChars ( # # # # # # # ) ######################################### sub getProcessChars { my $get_file_handles = shift(@_); my $include_children = shift(@_); my $pid = shift(@_); my $stats = shift(@_); my $result = shift(@_); my @cmdresult = (); my @fields = (); #always get the pid and the ppid my $args = "ppid pid"; #create ps argument string foreach $stat (@$stats) { $args .= " $stat"; } if ($^O eq "darwin") { $args .= " command"; } else { $args .= " args"; } if ( $^O eq "linux" ) { $cmd = "ps -www -eo '$args'"; } elsif ($^O eq "SunOS" or $^O eq "solaris") { $cmd = "/usr/bin/ps -ef -o '$args'"; } elsif ( $^O eq "aix" ) { $cmd = "/usr/sysv/bin/ps -A -o '$args'"; } elsif ( $^O eq "darwin" ) { $cmd = "ps awwxo '$args'"; } else { $cmd = "ps -ef -o '$args'"; } my $r = `$cmd` or die "Could not execute $cmd: $!"; # now we have list # of all the information we need. @lines = split("\n", $r); #get rid of text shift(@lines); #number of processes running $numlines = @lines; $numcols = scalar(@$stats) + $stat_offset; my $numargs = scalar(@$stats) + 3; $row = 0; foreach $line (@lines) { @tokens = split(" ",$line, $numargs); $col = 0; foreach $token (@tokens) { @cmdresult[($row*$numcols)+$col] = $token; $col++; } $row++; $commands{$tokens[1]} = $tokens[$numargs-1]; } @fields = split(' ', $args); getProcessCharsRec($pid, $include_children, $numcols, $get_file_handles, \@cmdresult, \@$result, \@fields); } #Effects: Returns the uptime of process P in seconds. i.e. the time it has # been running. sub getUptime { my $pid = shift(@_); $cmd = "ps -p $pid -o \"pid etime\" "; my $r = `$cmd` or die "Could not execute ps"; @lines = split("\n", $r); foreach $line (@lines) { @stats = split(" ", $line); if($stats[0] == $pid) { # this process return $stats[1]; } } }# end getUptime # Effects: Returns the sum of all the Open Filehandles (OF) for process # P of the type passed in. sub getFileHandles { (my $pid, my $include_child_procs) = @_; if($pid eq $$) { # we want to exclude this process return 0; } $cmd = "ps -A -o \"ppid pid\" "; my $file_count = 0; my $r = `$cmd` or die "Could not execute ps"; @lines = split("\n", $r); foreach $line (@lines) { @stats = split(" ", $line); if($stats[1] eq $pid) { # this process $file_count += countFileHandlesOfType_HP($stats[1]); } if($include_child_procs == 1 && $stats[0] eq $pid) { # child process $file_count += getFileHandles($stats[1], $include_child_procs); } } return $file_count; }#end getFileHandles sub countFileHandlesOfType_HP { (my $pid) = @_; $cmd = "$ENV{EMDROOT}/bin/nmupm nof $pid"; my $r = `$cmd`; if ($r =~ /em_result=(\d*)/) { return $1; } else { return 0; } }#end countFileHandlesOfType_HP # Effects: Returns the number of threads created by process P and its # child processes if include_children is // TRUE. If # include_children is FALSE, returns just the number of threads # created by process P. sub getThreads { my $pid = shift(@_); my $include_child_procs = shift(@_); $cmd = "ps -p $pid -o \"ppid pid nlwp\" "; my $thread_count = 0; my $r = `$cmd` or die "Could not execute ps"; @lines = split("\n", $r); foreach $line (@lines) { @stats = split(" ", $line); if($stats[1] eq $pid) { # this process $thread_count += $stats[2]; } if($include_child_procs == 1 && $stats[0] eq $pid) { # child process $thread_count += getThreads($stats[1], 0); } } return $thread_count; }#end getThreads # Effects: Returns the number of threads among the list of # threads sent as argument, which belong to a particular process sub getThreadCount_LNX { my $pid = shift(@_); my $threads = shift(@_); my $thread_count = 0; @lines = split("\n", $threads); foreach $line (@lines) { @stats = split(" ", $line); if($stats[1] eq $pid) { # this process $thread_count = $thread_count + 1; } if($stats[0] eq $pid) { # child process $thread_count += getThreadCount_LNX($stats[1], $threads); } } return $thread_count; } # Effects: Returns the Agent PID and Parent PID from emctl status agent output # emct status agent output sent as argument sub getPIDS{ my $x = shift(@_); my @lines = split("\n", $x); my $size = @lines; my @pids; my $count = 0; for (my $i=0; $i < $size; $i++) { ( $preStr , $postStr) = split ( /: / , @lines[$i]); if($preStr eq "Agent Process ID ") { $pids[0] = $postStr; } if($preStr eq "Parent Process ID ") { $pids[1] = $postStr; } } return @pids; } 1;