Ever read the ‘lsof’ utility man page? It’s a shame, because the idea of the utility is wonderful – list open files and who is using them.
I had need to see what files were in use by imapd on my server. “lsof | grep imapd” gave me far more than I needed, along with long lines of info I didn’t really need all of, and all the libraries in use, etc, etc. That’s when I thought, RTFM … so I did, and eventually gave up. Maybe I was having a bad day, but the manual seemed impenetrable, so I turned to
rolling my own.
I’d explored around the /proc file system a bit before, and was sure everything I need was there, and it turned out a lot easier than I’d thought. So here goes…
Under /proc, every process has a directory, with an entry called “cmdline” which gives access to that process’s command line arguments. There is a sub-directory called “fd” that contains links to each file the process has open. With this info I knocked together this little script, I called it ‘pof’:
#!/bin/sh # cd /proc while [ "$1" != "" ]; do for n in [1-9]* ; do if [ "$n" != "self" -a -f $n/cmdline ] then if grep "$1" $n/cmdline > /dev/null ; then cmd=`tr '\0' ' ' < $n/cmdline` printf "%-8d %s\n" $n "$cmd" for m in $n/fd/* ; do printf " %-14s %s %s\n" `stat --printf="%N" $m` done fi fi done shift done
It is called with an string or regular expression that you want to search each command line for. If it is found, the open file links are displayed for that process. So now ‘pof imapd’ gives me what I want.
The ‘cmdline’ file contains each argument of the command line as a null (‘\0’) terminated string, so I need to use ‘tr’ to convert the nulls to spaces before printing out.
On my system the imapd daemon is launched from inetd, so it’s first 3 files, stdin/stdout/stderr, are network sockets – so I need to dig a bit deeper and find out how to get the remote IP address of the socket.
Anyway I’m sure someone will tell me how easy ‘lsof’ is to use to get any info you want, but delving into /proc is fun!