Browsing all articles tagged with awk
Oct
4

Using PS to output human readable memory usage for each process using AWK

I ran into a little issue: I wanted to list the memory usage of each process, but I wanted it to be output in human readable form (as in “df -h”).  So, after a little Googling I found a forum thread which put the idea of using awk.  A little bit later I had the solution:

Here’s what you see with normal ps:

$ ps u
 
USER PID %CPU %MEM VSZ RSS TTY STAT START TIME COMMAND
kes1 12394 0.0 0.0 107356 2052 pts/1 Ss 08:15 0:00 -sh
kes1 12648 0.5 3.2 720808 527356 pts/0 S+ 08:16 0:16 /usr/lib64/R/bin/exec/R
kes1 13682 0.0 0.0 107360 2016 pts/3 Ss 08:18 0:00 -sh

Here’s what we want to see:

USER    PID     %CPU    %MEM            VSZ             RSS     TTY     STAT    START   TIME    COMMAND
kes1    12394   0.0     0.0            104.84Mb          2.00Mb  pts/1   Ss      08:15   0:00    -sh
kes1    12648   0.7     3.2            703.91Mb        515.00Mb  pts/0   S+      08:16   0:16    /usr/lib64/R/bin/exec/R
kes1    13682   0.0     0.0            104.84Mb          1.97Mb  pts/3   Ss      08:18   0:00    -sh

And here’s how we make that happen with awk:

ps u | awk '{
for ( x=1 ; x<=4 ; x++ ) { printf("%s\t",$x) } 
for ( x=5 ; x<=6 ; x++ ) {  if (NR&gt;1) { printf("%13.2fMb\t",hr=$x/1024) }  
else { printf("\t%s\t",$x)  } 
}
for ( x=7 ; x<=10 ; x++ ) { printf("%s\t",$x) } 
for ( x=11 ; x<=NF ; x++ ) { printf("%s ",$x) } 
print "" 
}'

What does this awk script do?

There are a few different things going on here.  First, we want to print out all the non-memory fields as tab-separated text.  Second, we want to print out the memory as formatted kb and not bytes.  Also, we want everything to line up. Finally, we want to print out the process name normally (using space and not using tab separation).

First, the script prints the first 4 fields:

for ( x=1 ; x<=4 ; x++ ) { printf("%s\t",$x) }

Then, we check to see if this is the header line or not. If it is the header line, then NR (the number of records read) will be 1. If it’s not, then NR will be greater than 1. For the header, we print out the text (adding some more tabs to line things up). For the memory fields, we use printf to format the byte count as human readable text.

for ( x=5 ; x<=6 ; x++ ) {  
if (NR>1) { printf("%13.2fMb\t",hr=$x/1024) }  
else { printf("\t%s\t",$x)  } 
}

Finally, we print the remaining PS fields as before, but then we switch to space-delimited fields for the process name and arguments, making sure to add a newline at the very end.

for ( x=7 ; x<=10 ; x++ ) { printf("%s\t",$x) } 
for ( x=11 ; x<=NF ; x++ ) { printf("%s ",$x) } 
print ""

Nothing to it!

%d bloggers like this: