#!/usr/bin/perl # # bottom - display bottom processes. Solaris, Perl. # # This is the opposite of top, it displays processes that are using the # least CPU. It is the companion to the "prstat" command. # # 25-Jun-2005, ver 0.91 # # USAGE: bottom [interval] # # THANKS: Ron Soutter, for suggesting this tool. # # COPYRIGHT: Copyright (c) 2005 Brendan Gregg. # # 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 (at your option) 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. # # (http://www.gnu.org/copyleft/gpl.html) # # 23-Jun-2005 Brendan Gregg Created this. ### Defaults $INTERVAL = 5; $ENV{PATH} = "/usr/bin"; $| = 1; ### Check arguments if (@ARGV > 0) { if ($ARGV[0] eq "-h" || $ARGV[0] eq "--help" || @ARGV > 1) { &usage(); } $INTERVAL = $ARGV[0]; $INTERVAL = 1 if $INTERVAL < 1; } ### Determine screen manipulation $CLEARSTR = `clear`; my ($row,$col) = &getwinsz(); $TOP = $row - 3; %State = qw(S sleep R run O cpu0 T stop Z zombie); # # --- Main --- # for (;;) { # read output from ps. if performance is a concern this could be # rewritten to read data from procfs directly; an example of doing # this in Perl is in my "prusage" tool. @Lines = `ps -eo pid,pcpu,user,vsz,rss,s,pri,nice,time,fname,nlwp`; chomp(@Lines); ### Process data foreach $line (@Lines) { ($pid,$pcpu,$rest) = split(' ',$line,3); next if $pid eq "PID"; $Sort{$pid} = $pcpu; $Data{$pid} = "$pcpu $rest"; } ### Build report $line = 0; @Output = (); foreach $pid (sort {$Sort{$a} <=> $Sort{$b}}(keys(%Sort))) { ($pcpu,$user,$vsz,$rss,$s,$pri,$nice,$time,$fname,$nlwp) = split(' ',$Data{$pid}); $nice -= 20; $s = $State{$s}; $vsz = &kbtohuman($vsz); $rss = &kbtohuman($rss); $out = sprintf("%6s %-8s %5s %5s %-6s %3s %4s %6s %3s%% %s/%s\n", $pid,$user,$vsz,$rss,$s,$pri,$nice,$time,$pcpu,$fname, $nlwp); unshift(@Output,$out); last if ++$line > $TOP; } ### Print report print $CLEARSTR; printf("%6s %-8s %5s %5s %-6s %3s %4s %6s %4s %s/%s\n", "PID","USERNAME","SIZE","RSS","STATE","PRI","NICE","TIME", "CPU","PROCESS","NLWP"); print @Output; ### Wait interval sleep($INTERVAL); } # usage - print usage and exit. # sub usage { print STDERR "USAGE: bottom [interval]\n"; exit 1; } # getwinsz - gets the terminal window size and returns it as x, y. # The default size returned is 24x80 if an error is encountered. # sub getwinsz { my $row = 24; my $col = 80; my ($xpix,$ypix,$winsize); my $TIOCGWINSZ = 21608; # check /usr/include/sys/termios.h open(TTY, "+