tc1364 has asked for the wisdom of the Perl Monks concerning the following question:

Can you please assit me with obtaining the "CPU states: 91.7% idle, 6.8% user, 0.7% kernel, 0.8% iowait, 0.0% swap" line from the top command? Looking at man for top didn't help.
#!/usr/bin/perl open PIPE, "/usr/local/bin/top -b -n 3 |" or die "Cannot open"; my $output = join '', <PIPE>; close PIPE or die "Running top failed"; print "$output\n"; exit(0);
The output looks like the below currently.
load averages: 0.26, 0.24, 0.30 16:02:45 171 processes: 168 sleeping, 1 running, 1 zombie, 1 on cpu Memory: 1024M real, 767M free, 92M swap in use, 1732M swap free PID USERNAME THR PRI NICE SIZE RES STATE TIME CPU COMMAND 6451 pc2587 1 11 0 984K 704K sleep 0:26 5.36% br 5983 dw3586 1 48 0 984K 704K sleep 1:19 0.35% br 5962 dw3586 1 48 0 984K 704K sleep 1:39 0.35% br

Edited by Arunbear: Changed title from 'PIPE', as per Monastery guidelines; and added code tags around output.

Replies are listed 'Best First'.
Re: Obtaining data from the top command via a pipe
by Tanktalus (Canon) on Aug 08, 2005 at 21:21 UTC

    You don't really want to join the pipe. Nor do you likely want "-n 3". You probably want "-n 1".

    #!/usr/bin/perl open PIPE, "/usr/local/bin/top -b -n 1 |" or die "Cannot open pipe"; my ($output) = grep /^CPU states:/, <PIPE>; close PIPE or die "Running top failed"; print "$output\n"; exit(0);

    Hope that helps,

Re: Obtaining data from the top command via a pipe
by davidrw (Prior) on Aug 08, 2005 at 21:48 UTC
    Do you need this in perl? From command line, it would just be:
    top -b -n 1 | grep ^CPU
    if you want it in perl, probably (other ways of course) want a loop something like:
    while(<PIPE>){ next unless /^CPU.*? ([0-9.]+)% idle, ([0-9.]+)% user/; my ( $idle, $user ) = ( $1, $2 ); ... last; }
Re: Obtaining data from the top command via a pipe
by AReed (Pilgrim) on Aug 08, 2005 at 21:46 UTC
    In batch mode, one iteration of top won't display the information that you are interested in. Add the -d2 option to run a couple of iterations, and the second should include the CPU info.
    #!/usr/bin/perl use warnings; use strict; open (PIPE, "/usr/local/bin/top -b -d2 |") or die "Cannot open top: $! +"; while (<PIPE>) { if (/^CPU/) { print; last; } } close(PIPE); exit(0);
    I tested this on a Sun-Fire-280 running Solaris 9 and I am not a Unix guru so your mileage may vary. Best of luck.

    Updated: removed temporary variable for input line.

      Thank you, this really helps allot!
Re: Obtaining data from the top command via a pipe
by anonymized user 468275 (Curate) on Aug 09, 2005 at 13:33 UTC
    Sorry guys, but the problem is that top prints the page without the line for the CPU states, leaving that line blank. Then it has to do screen cursor positioning to update that line in realtime. But the first time it tries, it discovers that that the pipe to which you are directing output cannot accept ANSI escape sequences (needed to position the cursor) so it exits before that point.

    Piping to tee doesn't work either because then tee has access to the screen device but top still hasn't got it and exits just as quickly leaving tee to duplicate the same problem.

    Update: Perhaps something like Test::Expect will be able to emulate an ANSI terminal to top's satisfaction.

    One world, one people