Prstat Equivalent

Linux equivalent of prstat -a

MarkRound was [looking] for a Linux equivalent to prstat -a from Solaris, which gives an output similar to:

 NPROC USERNAME SIZE  RSS MEMORY   TIME CPU
  22 root    57M  35M  3.6%  1:21:22 9.1%
   3 mround   13M 8672K  0.9%  0:00:00 0.1%
   1 qmailq  1000K 704K  0.1%  0:00:00 0.0%
   1 qmailr  1000K 640K  0.1%  0:00:00 0.0%
   1 qmails  1064K 768K  0.1%  0:00:00 0.0%
   1 qmaild  1784K 1384K  0.1%  0:00:00 0.0%
   2 qmaill  2032K 1440K  0.1%  0:00:00 0.0%
   1 mysql   381M  29M  3.0%  0:01:44 0.0%

Solutions

  • Jim suggested w, however this only shows total CPU time and CPU time of one current process
  • AlanPope suggested [nmon] which can run either interactively or an analyser at a later date
  • Dominic's bit of Perl, based on SirajSidRakhada's suggestion of using ps or /proc:
#!/usr/bin/perl
# Rough port of "prstat -a" released to the public domain
#  -- Dominic Cleal (dominic at computerkb dot co dot uk)
 
my @ps = `/bin/ps aux`;
my @headers = split(/\s+/, shift(@ps));
my %users;
 
foreach (@ps) {
  chomp;
  my $col = 0;
  my %ps_entry;
  foreach (split(/\s+/, $_, $#headers + 1)) {
    $ps_entry{$headers[$col]} = $_;
    $col++;
  }
 
  next unless exists $ps_entry{USER};
  $users{$ps_entry{USER}} = { nproc=>0, size=>0, rss=>0, mem=>0, time=>0, cpu=>0 } unless exists $users{$ps_entry{USER}};
  my $user = $users{$ps_entry{USER}};
 
  $user->{nproc}++;
  $user->{size} += $ps_entry{VSZ} if exists $ps_entry{VSZ};
  $user->{rss} += $ps_entry{RSS} if exists $ps_entry{RSS};
  $user->{mem} += $ps_entry{'%MEM'} if exists $ps_entry{'%MEM'};
  $user->{cpu} += $ps_entry{'%CPU'} if exists $ps_entry{'%CPU'};
  $user->{time} += ($1 * 60) + $2 if (exists $ps_entry{'TIME'} && $ps_entry{'TIME'} =~ /^([0-9]+):([0-9]+)$/);
}
 
print "NPROC\tUSER\tSIZE\tRSS\tMEMORY\tTIME\tCPU\n";
foreach (sort { $users{$b}{cpu} <=> $users{$a}{cpu} } keys(%users)) {
  printf("%d\t%s\t%d\t%d\t%.1f\%\t%.2d:%.2d\t%.1f\%\n", $users{$_}{nproc}, $_, $users{$_}{size}, $users{$_}{rss}, $users{$_}{mem}, ($users{$_}{time} / 60), ($users{$_}{time} % 60), $users{$_}{cpu});
}

Output:

 $ perl prstat.pl
 NPROC  USER   SIZE  RSS   MEMORY TIME  CPU
 48   root   102372 46580  2.1%  11:06  3.6%
 39   dominic 907404 414804 24.7%  07:42  2.4%
 1    uml-net 1600  416   0.0%  00:00  0.0%
 1    102   10604  1448  0.0%  00:00  0.0%
 1    101   2196  572   0.0%  00:00  0.0%
 2    daemon  3692  784   0.0%  00:00  0.0%
 1    www-data 2172  744   0.0%  00:00  0.0%

It has the following problems:

  • Doesn't change units of memory usage (should be a CPAN module for that)
  • Columns are only done with tabs so they break with long usernames