Have you ever wanted to monitor some processes on your system using a Bash script? Well, I have had to many times. Usually I’m running a script or program that is processing large amounts of data and I want to keep an eye on it’s progress. Well, it’s actually quite easy.
Peaking At Processes
The foundation of this is the
ps command, which will report a snapshot of the current processes. You can look at the man page to get an idea of all the options you have for listing processes. If you know the PID (process ID) of what you want to monitor then you can run the command like this:
ps up <PID>
u option specifies to display in a user-oriented format. The
p allows you to specify the PID of whichever process you would like listed. And of course you would substitute <PID> with the actual numeric PID. Of course I usually like to keep an eye on several different processes, who’s PIDs I may not actually know. In that case what I do is get a listing of all of the processes and use the
grep command to filter out just the ones I am interested in. It usually looks something like this:
ps aux | head -n 1 ps aux | egrep "foo|bar" | grep -v grep
There are several things going on here. When I use grep to filter out the lines I am interested in it also filters out the headers, which I would like to see. So the first line makes our
ps call and pipes it’s output to the
head command with the “
-n 1” option telling it to list only the first line. Next I make the ps call yet again, this time piping it’s output to the
egrep command (extended grep). Notice that the pipe in the
egrep command argument is inside quotes and stands for the logical OR operator. This will do a pattern match for the strings “foo” or “bar” within the
ps command output. I then pipe this into another
grep command with the
-v option (inverse) matching the string grep. This is because I don’t want to actually list the
grep process which I just fired off to perform my filtering.
Now this is all fine and dandy, but I do not want to sit around typing out this command over and over again. Even if I threw this all into a Bash script file I would have to continue executing the file over and over. So instead I put this into an infinite loop. Wait! Aren’t infinite loops bad? Not if that’s what you intended to do… and so long as you have a way out of the loop. Using the simple
while syntax gives me something like this:
while true do clear ps aux | head -n 1 ps aux | egrep "foo|bar" | grep -v grep sleep 5 done
Now it runs my
ps commands over and over again. I have started the commands with
clear which should clear the console so that my process listing will remain at the top of whatever terminal I happen to be using. I have also added
sleep 5 to the end of the commands. This of course tells the loop to wait 5 seconds. If this was not here the loop would execute so quickly that I would not be able to read it.
So this gives me a constantly updating view of some processes running on my machine. So what? Well, this is just the beginning. The sky is the limit here really. Whatever other system commands and/or scripts that I’ve created can be mashed into this loop to do whatever monitoring I want. Take the following for instance:
#!/bin/bash while true do clear echo ps aux | head -n 1 ps aux | egrep "foo|bar" | grep -v grep echo find /usr/some/dir -iname "*.xml" | wc -l echo du -sh /usr/some/dir echo date echo sleep 5 done exit 0
In this example I retrieve my process listing as usual. I also perform a count of XML files in some directory which I may happen to be generating output to. After that I use
du to get the disk usage of that output directory. I also output the date, which consequently will include the time.
I hope this gives you some ideas as to the power of using Bash shell scripts to build simple or complex monitoring solutions. I usually include a flag within in my loop that causes it break when my processes are done and then fire off a status email. This way even if I stop monitoring my processes I’ll have a record of when it was completed sitting in my Inbox.