Sunday, September 23, 2007

Shell script: process finding on steroids

Albeit being a bit of an off-topic subject, today's post concerns a little unix admin script I've done...

Apart from my main focus on the research lab (i.e., doing research on Web user experience things for my PhD) , I've also got administration responsabilities on our servers, desktops, etc.

Since our server is a Linux based 1U rack machine, handling Web and e-mail stuff, we have to stay on top with all the things - processes - that are running in it. The reason for this is surveillance is to avoid it to become a zombie of a botnet and, consequently, used to send huge amounts of spam around the world.

From the latest count on our lab's website, we've got 72 researchers listed. Anyone with a bit of unix (or even Windows) experience on administrating a server for this number of persons knows that quickly finding the needle on the haystack (i.e., finding a problem on the server) may be cumbersome.

One of the things I wanted to do really quickly was to know more things about the processes each user is running, as a user running an abnormal number of processes could indicate that an account had been compromised. I wanted this really badly, as doing a simple ps, would yield pages and pages of running processes listings.

That's when shell scripts come to rescue.

With a bit of knowledge, some Google kung fu, and an almost obsessive use of digital duct tape, I've come up with a script that quickly summarizes how many processes for each application/utility are being run by each user.

Here it is on all of its glory:


#/bin/bash
ps auex | grep -v ^USER | awk '{print $1, $11}' | sort | uniq -c | awk 'BEGIN{m="_";f=1}{if($2!=m){m=$2;if(f!=1)print "";printf("%s ::",$2);f=0;}printf(" [%s %s]",$1,$3)}END{print ""}'


This script's output lines are similar to this:


rlopes :: [2 awk] [2 -bash] [1 grep] [4 imap] [1 ps] [1 sort] [1 sshd:] [1 uniq]


From this you can see that I'm running 4 instances of imap (silly server...) and other assorted stuff. Similar lines appear for each user with, at least, one running process on his/her behalf. Much, much, much better than using "ps | less" all the time :)

Drilling through that cryptic script, here's the rational behind it:

ps auex lists all processes. Really all of them.
grep -v ^USER removes ps's output headers. No garbage, thanks!
awk '{print $1, $11}' filters just user names and process names.
sort, well, sorts by user name.
uniq -c removes all repeated entries, but keeps the number of process copies running on the system.
awk 'BEGIN{m="_";f=1}{if($2!=m){m=$2;if(f!=1)print "";printf("%s ::",$2);f=0;}printf(" [%s %s]",$1,$3)}END{print ""}' pretty prints this information, with one concise line per user.

Use this script at your will and, please, feel free to make suggestions and improvements!