“Selective Top” Bash Script

In my daily work on linux, I constantly have several tabs open in my console app for various CLI activites. Normally, when I log in to a session, Yakuake auto-starts and I immediately open four tabs in it. Tab four becomes a system monitor through the use of the “top” command, tab one becomes an SSH window to my home server, and the other two are open for whatever.

Occasionally, I’ll want to keep an eye on specific processes and their resource usage, but they won’t show up in my “top” screen, no matter how I sort the fields. At this point, I have to use “ps” to find the PID (process ID) of each process I want to watch and add each PID to the end of the “top” command (using the -p switch for each PID), just to watch a few specific processes.

This little process is well-defined and repeating. Just the kind of task computers were designed to handle. I wrote a bash script which takes any number of arguments — all of them names of processes you want to watch — finds all related PIDs, and tacks them on to a top command.

#!/bin/bash

ps=""

for p in $*; do
    ps="$ps `ps -e | grep $p | awk '{print $1}' | sort -n | sed 's/^/-p /' | tr '\n' ' '`"
done

while [ `echo "$ps" | grep -c "  "` -ne 0 ]; do
    ps=`echo "$ps" | sed 's/  / /'`
done
ps=`echo "$ps" | sed 's/\(^\s*\)\|\(\s*$\)//'`

if [ -z "$ps" ]; then
    echo "No processes found."
else
    top $ps
fi

Please only use the above as a reference! The script uses a lot of single quotes, which WordPress likes to convert to “smart” quotes. To see the script as it should be, you can view the script as a text file.

The first chunk (”for p in $*…”) iterates over all the arguments, pulling out all the associated PIDs. The second block (”while…”) replaces multiple spaces with single spaces within the extracted process list, and trims any whitespace off of the beginning and end, to prepare the string for the test at the end. The last part (”if [ -z…”) checks if the process list is empty or not (if it’s all spaces, it’s “not”). If it is empty, the script alerts you and exits — you won’t get an empty top list (or full, since there are no arguments passed). If it’s not empty, we can assume we found some PIDs, so we tack that on to the top command and take you straight there.

If you want to use this, just stick it in an executable file in your path (see “echo $PATH” at the command line); I simply named mine “btm”, but it doesn’t matter what you call it. If you have any command line arguments you like to pass on to top, you can stick them between “top” and “$ps” in the “else” part of the script. Once it’s all set up, just call the script with the process names you want to watch:

$ btm rsync firefox thunderbird

Keep in mind that this will only work with processes that are currently running — once that rsync job is done, it’ll disappear from the list, but no new rsync jobs will show up unless you re-run the script.

1 Comment:

  1. Thanks. That’s exactly what I was looking for!

    Needed to monitor mysql and java worker processes.

    Thanks again!

No Pingbacks