#!/usr/bin/perl
#By Jepri of PerlMonks
#
#Bottom complements top by showing you processes that are being
#created or destroyed as programs start up and shut down.
#
#It was originally written to help me figure out what a naughty
#third party vendor program was doing (forking and execing), but
#when I looked around there didn't seem to be anything like this.
#
#It will probably only work with Linux /proc, and could easily be
#adapted to any other OS with the addition of parsers for other /procs
#
#Licensed under the GPL, which is longer than this program. Go
#get your own copy
use strict;
if ( grep {/-h|-\?|help/} @ARGV)
{
print "bottom - Display processes as they are created or destr
+oyed";
print "\n\nShows you processes as they are started and stopped
+.\n";
print "Note that there is a minimum time that we can measure -
+ \n";
print "if a process starts and stops in under about 10ms we wo
+n't\n";
print "see it at all.\n\n";
print "Options are:\n\n";
print "-ts or --timestamp Print the time\n";
print "-u or --user Print who owns(owned) the process\
+n";
print "-v or --verbose Print bells AND whistles\n";
print "\n\n\n";
exit;
}
my %ps;
my %old;
my $timestamp=(grep {/--timestamp|-ts/} @ARGV) ? 1 : 0 ;
my $displayuser=(grep {/--user|-u/} @ARGV) ? 1 : 0 ;
if ( grep {/-v|--verbose/} @ARGV)
{
$timestamp=1;
$displayuser=1;
}
while (1)
{
opendir DH, "/proc";
my @procs = readdir(DH);
close DH;
my %new;
foreach ( @procs )
{
$new{$_} = 1 if ($_ > 0);
}
my ($h1, $h2) = cmp_hsh( \%new, \%old);
%old = %new;
}
{
my %registry;
my %num_of;
sub regdump
{
return join(",", keys %registry);
}
#Add a key-value pair to the registry
sub reg
{
my ( $key, $val ) = @_;
$registry{$key} = $val;
}
#Given a key, return the value stored
sub what
{
my $key = shift;
return $registry{$key};
}
#Given a key, delete it and its value
sub unreg
{
my $key = shift;
delete $registry{$key};
}
}
sub get_proc_name
{
my $id = shift;
open FH, "/proc/$id/status";
my $name = <FH>;
chomp $name;
$name =~ s/Name:\s+//;
if ( $displayuser )
{
my $user;
grep { (/Uid:\s+(\d+)/) && ($user=getpwuid($1)) } <FH>
+;
$name.="\t(".$user.")";
}
close FH;
return $name;
}
#Return a timestamp
sub time_stamp
{
if ( $timestamp )
{
my($sec, $min, $hour, $mday, $mon, $year, $wday, $yday
+, $isdst) = localtime(time);
my $ts = $mday.'/'.$mon.'/'.(1900+$year).':'.$hour.':'
+.$min.':'.$sec;
return $ts."\t";
}
return "";
}
#Figure out which keys have been added and which have been
#deleted, print them out with appropriate markings.
sub cmp_hsh
{
my ( $h1, $h2 ) = @_;
my ( %oh1, %oh2);
foreach ( keys %{ $h1 } )
{
unless ( $h2->{$_} )
{
$oh1{$_}=get_proc_name($_);
reg($_, $oh1{$_});
print time_stamp(), "^^^ ", what($_), "\n";
}
}
foreach ( keys %{ $h2 } )
{
unless ( $h1->{$_} )
{
print time_stamp(), "vvv ", what($_), "\n";
$oh2{$_}=what($_);
unreg($_);
}
}
return \%oh1, \%oh2;
}
|