#!/pro/bin/perl use Tk; use Time::localtime; $width = 80; to_background (); InitTop (); MainLoop; ### ########################################################################### sub to_background { setpriority $pid, $$, 20; my $pid = fork; if ($pid < 0) { print STDERR "Unable to run in the background, cannot fork: $!\n"; exit $?; } $pid and exit 0; } # to_background sub InitTop { my $f; chomp ($HOST = `hostname`); $top = MainWindow->new (-cursor => "top_left_arrow", -name => "Top"); $top->title ("XTOP $HOST"); $top->bind ("q" => sub {$top->destroy}); $f = $top->Frame (-relief => "flat")->pack (-fill => "both", -side => "top"); $f->Label (-text => "System: $HOST")->pack (-fill => "both", -side => "left"); $sysdate = ctime (time); $f->Label (-textvariable => \$sysdate)->pack (-fill => "both", -side => "right"); $f = $top->Frame (-relief => "flat")->pack (-fill => "both", -side => "top"); $sysload = "Load avarages: "; $f->Label (-textvariable => \$sysload)->pack (-fill => "both", -side => "left"); $f = $top->Frame (-relief => "flat")->pack (-fill => "both", -side => "top"); $sysproc = "0 processes: 0 sleeping, 0 running, 0 zombies"; $f->Label (-textvariable => \$sysproc)->pack (-fill => "both", -side => "left"); %state = ( "0" => "nonexistent", "A" => "active ", "S" => "sleeping ", "W" => "waiting ", "R" => "running ", "I" => "idle ", "Z" => "terminated ", "T" => "stopped ", "X" => "growing "); $ENV{UNIX95} = 1; $pslist = $top->Scrolled ("ROText", -scrollbars => "e", -wrap => "none", -height => 20, -width => $width)->pack ( -expand => 1, -fill => "both", -side => "left"); $pslist->insert ("end", "PROcess list\n"); #$pslist->bind ("q" => sub {$top->destroy}); UpdateTop (); $top->repeat (2000, \&UpdateTop); } # InitTop sub pslist { my $pcpu_ok = 1; # Got patched ps from hp (02 Mar 1999) my @ps = $pcpu_ok ? `ps -e -otty,pid,user,pri,nice,state,vsz,time,pcpu,args` : `ps -e -otty,pid,user,pri,nice,state,vsz,time,cpu,args`; shift @ps; # Skip header, creating my own # Not all unix flavours use the same -o syntax my $hdr = " TTY PID USERNAME PRI NI STATE SIZE TIME \%CPU COMMAND\n"; my %cntproc = (); # Positions are based on reformatted output my @s = ( [ 52, 5], # %CPU [ 39, 6], # SIZE [ 45, 7], # TIME [ 27, 2], # NICE ); @ps = sort { substr ($b, $s[0][0],$s[0][1]) <=> substr ($a, $s[0][0],$s[0][1]) || substr ($b, $s[1][0],$s[1][1]) <=> substr ($a, $s[1][0],$s[1][1]) || substr ($b, $s[2][0],$s[2][1]) cmp substr ($a, $s[2][0],$s[2][1]) || substr ($a, $s[3][0],$s[3][1]) <=> substr ($b, $s[3][0],$s[3][1]) || $a cmp $b; } map { s/^\s+//; my @x = split m/\s+/, $_, 10; $x[0] =~ s/\?/-/; $cntproc{$x[5]}++; $x[5] =~ s/(.)/$state{$1}/; my @t = ((reverse split m/:/, $x[7]), 0, 0, 0); $x[7] = sprintf ("%4d:%02d", $t[2] * 60 + $t[1], $t[0]); $pcpu_ok and $x[8] *= 100.; sprintf "%6s %6d %-8s %3d %2d %-.8s %6d%6s%5.1f %s", @x; } @ps; $sysproc = sprintf ("%d processes: %d sleeping, %d running, %d zombies", scalar @ps, $cntproc{S}, $cntproc{R}, $cntproc{Z}); # unshift @ps, "0----+----1----+----2----+----3----+----4----+----5----+----6----+----7\n"; join "", $hdr, @ps; } # pslist sub ruptime { my $r; ($r = `rup localhost`) =~ s/.*l(oad.*\d)/L$1/; # ($r = (grep m/^$HOST\b/, `ruptime`)[0]) =~ # s/.*load\s+(.*\d)\s*/Load avarage: $1/; chomp $r; $r; } # ruptime sub UpdateTop { $sysdate = ctime (time); $sysload = ruptime; $pslist->delete ("1.0", "end"); $pslist->insert ("end", &pslist); } # UpdateTop