25 March 2011

Finding Open Files in FreeBSD

Following up the same in Solaris, here's how to identify open files on
a particular filesystem (FS) in a FreeBSD environment.  Our host details
for this are:
        HOST:           berkeley
        PROMPT:         berkeley [0]
        OS:             FreeBSD 6.2
        NOTE:           The following should likely work on prior FreeBSD
                        versions and has been verified to work up through
                        FreeBSD 8.x.
Like in the Solaris writeup, we'll be looking at open files in /var.
To start, we see that /var is its own FS and then use 'fstat' to see if
any processes have any opened files under "/var":
        berkeley [0] /bin/df -h /var
        Filesystem     Size    Used   Avail Capacity  Mounted on
        /dev/da0s1d    1.9G    210M    1.6G    12%    /var
        berkeley [0] /usr/bin/fstat -f /var
        USER     CMD          PID   FD MOUNT      INUM MODE         SZ|DV R/W
        root     cron         666   wd /var     164864 drwxr-x---     512  r
        root     cron         666    3 /var     141409 -rw-------       3  w
        smmsp    sendmail     660   wd /var     188423 drwxrwx---   63488  r
        smmsp    sendmail     660    4 /var     188428 -rw-------      49  w
        root     sendmail     654   wd /var     188420 drwxr-xr-x     512  r
        root     sendmail     654    5 /var     141408 -rw-------      78  w
        root     snmpd        593    3 /var     141354 -rw-r--r--  125439984  w
        root     syslogd      532    3 /var     141398 -rw-------       3  w
        root     syslogd      532    9 /var     141336 -rw-r--r--   82274  w
        root     syslogd      532   10 /var     141343 -rw-------  308911  w
        root     syslogd      532   11 /var     141331 -rw-------   66836  w
        root     syslogd      532   12 /var     141316 -rw-r-----  7562200  w
        root     syslogd      532   13 /var     141327 -rw-r--r--      60  w
        root     syslogd      532   14 /var     141333 -rw-------      60  w
        root     syslogd      532   15 /var     141317 -rw-------   45648  w
        root     syslogd      532   16 /var     141326 -rw-------      60  w
        root     syslogd      532   17 /var     141332 -rw-r-----      60  w
        root     syslogd      532   18 /var     141330 -rw-r-----      60  w
From the above we have 18 processes running with opened files in "/var".
If we wanted to get more information specifically on those processes,
we can use the output of 'fstat' (piped to 'awk' to get only the numeric
PID) as input to 'ps':
        berkeley [0] /bin/ps p `/usr/bin/fstat -f /var | /usr/bin/awk '!/PID/ {print $3}'`
          PID  TT  STAT      TIME COMMAND
          532  ??  Is   402:21.49 /usr/sbin/syslogd -s
          593  ??  S    213:23.47 /usr/local/sbin/snmpd -a -p /var/run/snmpd.pid udp:17
          654  ??  Ss    23:20.32 sendmail: accepting connections (sendmail)
          660  ??  Is     0:36.90 sendmail: Queue runner@00:30:00 for /var/spool/client
          666  ??  Is     4:37.89 /usr/sbin/cron -s
Now that we know there are processes with opened files in "/var", let's
see which particular files are opened.  By passing off the output of
'fstat' to a while loop, we can use 'find' called from 'awk' to processes
each line of 'fstat' output and give us the numeric PID and the file
path(s) each process is holding open:
        berkeley [0] /usr/bin/fstat -f /var | while read line ; do
        > echo "$line" | /usr/bin/awk '!/PID/ {printf("%s:  ", $3);
        > system("/usr/bin/find " $5 " -inum " $6)}' ; done
        666:  /var/cron
        666:  /var/run/cron.pid
        660:  /var/spool/clientmqueue
        660:  /var/spool/clientmqueue/sm-client.pid
        654:  /var/spool/mqueue
        654:  /var/run/sendmail.pid
        593:  /var/log/snmpd.log
        532:  /var/run/syslog.pid
        532:  /var/log/messages
        532:  /var/log/security
        532:  /var/log/auth.log
        532:  /var/log/maillog
        532:  /var/log/lpd-errs
        532:  /var/log/xferlog
        532:  /var/log/cron
        532:  /var/log/debug.log
        532:  /var/log/slip.log
        532:  /var/log/ppp.log

see also:
    Finding Open Files in Solaris
    Finding Open Files in Linux

4 comments:

Anonymous said...

get an error from your code:

# /bin/ps p `/usr/bin/fstat -f /var | /usr/bin/awk '!/PID/ {print $3}'`
/PID/: Event not found.

troy said...

Anonymous,

What version of FreeBSD are you using? I've just tried that same command string on both a FreeBSD 8.2 and FreeBSD 5.4 install and it completes without error returning similar output to that in my post. I'm not doubting the error you received, just without a additional information, I'm at a loss for why you received it.

--troy

Anonymous said...

@anonymous,
the problem is that your shell is doing a history lookup (due to the '!' in the script).
Scott

troy said...

Scott,

Good catch on that. Since I typically use ksh and don't have '!' bound to anything such as history substitutions, I didn't even thing about that as the cause. Again, nice catch.

--troy