UPDATE: 15 Oct 2010 This script is very buggy. I leave it here as a lesson in bugginess. :-) Please see the script in the reply below, which works better. This didn't need threads, nor IO::Select, but it was a hack I came up with while learning. Top output is hard to process completely. Either you get only the top few pids, depending on the size of the terminal you are using, or you get leftover fragments from the previous run in the pipe.

The improved version below, gets all pids, at the expense of forking off top on every refresh.

I wanted to monitor the cpu and ram usage of some test apps, and found it hard to follow the jumping pid sort of top. So I run top in a thread in batch mode, and present it's output sorted by pid (so it dosn't jump ) and made crude, but usable, bar graphs for the cpu and mem.

It dosn't use too much cpu at the rates i've built-in, which is .5 seconds for top and 1 second for the Tk display. You can speed things up if desired, but at the expense of increasing cpu usage to over a few percent.

There is one unexplained bug I've found, related to running top in -b (batch mode). One of my apps, "/home/zentara/bin/claws" ( a mail program), shows up as the number 3 as a command name in batch mode. I can't explain it, and figure it's a small bug in top? Otherwise it works fine.

A mouse button 1 click on an app, will present a kill dialog for that pid.

#!/usr/bin/perl use warnings; use strict; use Tk; use Tk::Dialog; use threads; use threads::shared; # 1 setting for big or default font, see lines 41 - 42 #mouse button 1 click on an app, will ask if you want to kill it #create thread first, to make Tk thread-safe my $buf : shared; my $thread_die : shared; $buf = ''; $thread_die = 0; my $thread = threads->new( \&work ); #my %pid; #global to hold pid data my $mw = new MainWindow; $mw->protocol('WM_DELETE_WINDOW' => sub { + $thread_die = 1; $thread->join; exit; + }); my $tframe = $mw->Frame(-bg=>'black')->pack(-fill=>'x'); $tframe->Label(-text=> 'RAM ------',-bg=>'black',-fg=>'red')->pack(-si +de=>'left'); $tframe->Label(-text=> 'CPU ------',-bg=>'black',-fg=>'green')->pack(- +side=>'left'); my $canvas = $mw->Scrolled('Canvas', -bg =>'black', -height => 500, -width => 600, -scrollregion => [0,0,400,500], -scrollbars => 'osoe' )->pack(-expand=>1,-fill=>'both'); my $realcan = $canvas->Subwidget('scrolled'); my $font = 'default'; #my $font = $mw->fontCreate('font', # -family=>'arial', # -weight=>'bold', # -size=>int(-18*18/14)); my $fonttest = $canvas->createText(0,0, -fill => 'black', -text => 'W', -font => $font, ); my ($bx,$by,$bx1,$by1) = $canvas->bbox($fonttest); my $f_w = $bx1 - $bx; my $f_h = $by1 - $by; $canvas->delete($fonttest); my $id = Tk::After->new($mw, 1000,'repeat',\&refresh); MainLoop; sub refresh{ my %pid; $canvas->delete('all'); # print "$buf\n"; my @data = split(/\n/, $buf); foreach my $line(@data){ $line =~ s/^\s+//; if($line =~ /^\d+/){ my @p = split(/\s+/, $line); my $pid = $p[0]; $pid{$pid}{'user'} = $p[1]; $pid{$pid}{'command'} = $p[11]; $pid{$pid}{'mem'} = $p[9]; $pid{$pid}{'cpu'} = $p[8]; } } my $count = 1; foreach my $key(sort {$a<=>$b} keys %pid){ my $string = ' ' x ( 7 - length( $key ) ) . $key; $pid{$key}{'user'} .= ' ' x ( 15 - length( $pid{$key}{'user'} ) +); $string .= ' '.$pid{$key}{'user'}.' '.$pid{$key}{'mem'}.' '. $pid{$key}{'cpu'}.' '.$pid{$key}{'command'}; my $text = $canvas->createText(0, $count * $f_h , -fill => 'orange', -text => $string, -font => $font, -anchor => 'nw', -justify => 'left', -tags => [$key,'string'], ); #500 pixel max width, so 500 = 1.0 or 100% $canvas->createLine($f_w, $count * $f_h - 2, $f_w + $pid{$key}{'cpu'} * 5 , $count * $f_h + - 2 , -fill => 'green', -width =>5, # -stipple =>'gray75', ); $canvas->createLine($f_w, $count * $f_h + $f_h , $f_w + $pid{$key}{'mem'} * 5 , $count * $f_h ++ $f_h , -fill => 'red', -width =>5, # -stipple =>'gray75', ); $canvas->createLine($f_w, $count * $f_h + 1.5*$f_h, $f_w + 500 , $count * $f_h + 1.5*$f_h , -fill => 'white', -dash => '- -', -width =>1, ); $count +=2; } $canvas->CanvasBind("<Button-1>",sub{ my ($tag) = grep /\d+/, $canvas->gettags("current"); if( defined $tag){ &do_dialog($tag) } } ); $canvas->bind( 'string', '<Enter>' => sub{ my ($tag) = grep /\d+/, $canvas->gettags("current"); if( defined $tag){ my ($current) = $canvas->find('withtag','current'); $canvas->itemconfigure($current,-fill=>'white'); } }); $canvas->bind( 'string', '<Leave>' => sub{ my ($tag) = grep /\d+/, $canvas->gettags("current"); if( defined $tag){ my ($current) = $canvas->find('withtag','current'); $canvas->itemconfigure($current,-fill=>'orange'); } }); my (undef,undef,$x,$y) = $realcan->bbox("all"); if( defined $x){ $realcan->configure(-scrollregion => [0,0,$x + 30, $y+30 ] ); } } ################################################################## sub work{ $|++; use IPC::Open3; use IO::Select; my $pid1 = open3(0, \*READ, 0,"top -b -d .5"); waitpid($pid1, 1); my $sel = new IO::Select(); $sel->add(\*READ); while(1){ foreach my $h ($sel->can_read){ sysread(READ,$buf,8192); # print "$buf\n\n"; } if( $thread_die == 1 ){return} #kill thread } } ##################################################################### sub do_dialog { my $pid = shift; $pid += 0; #make numeric my $dlg = $mw->Dialog( -title=>"Kill pid # $pid?", -buttons => ["Cancel", "No", "Yes"], -default_button => "No", -text => "Kill pid # $pid ?", -font => "Helvetica" ); my $result = $dlg->Show(); if($result eq 'Yes'){ kill 9, $pid } } #####################################################################

In reply to ztk-visual-top-w-kill by zentara

Title:
Use:  <p> text here (a paragraph) </p>
and:  <code> code here </code>
to format your post, it's "PerlMonks-approved HTML":



  • Posts are HTML formatted. Put <p> </p> tags around your paragraphs. Put <code> </code> tags around your code and data!
  • Titles consisting of a single word are discouraged, and in most cases are disallowed outright.
  • Read Where should I post X? if you're not absolutely sure you're posting in the right place.
  • Please read these before you post! —
  • Posts may use any of the Perl Monks Approved HTML tags:
    a, abbr, b, big, blockquote, br, caption, center, col, colgroup, dd, del, details, div, dl, dt, em, font, h1, h2, h3, h4, h5, h6, hr, i, ins, li, ol, p, pre, readmore, small, span, spoiler, strike, strong, sub, summary, sup, table, tbody, td, tfoot, th, thead, tr, tt, u, ul, wbr
  • You may need to use entities for some characters, as follows. (Exception: Within code tags, you can put the characters literally.)
            For:     Use:
    & &amp;
    < &lt;
    > &gt;
    [ &#91;
    ] &#93;
  • Link using PerlMonks shortcuts! What shortcuts can I use for linking?
  • See Writeup Formatting Tips and other pages linked from there for more info.