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>
The 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.
The Loop
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.
Automation
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.