前回紹介したように、lsofコマンドでは、開かれているファイルと、それを開いているプロセスの情報を簡単に取得することができる。基本的には、次のように何も引数を指定しないで実行すれば、欲しい情報を得られるようになっている。
% lsof
COMMAND PID USER FD TYPE DEVICE SIZE/OFF NODE NAME
kernel 0 root cwd VDIR 0,90 512 2 /
kernel 0 root rtd VDIR 0,90 512 2 /
init 1 root cwd VDIR 0,90 512 2 /
init 1 root rtd VDIR 0,90 512 2 /
init 1 root txt VREG 0,90 1061880 2809013 /sbin/init
adjkerntz 148 root cwd VDIR 0,90 512 2 /
adjkerntz 148 root rtd VDIR 0,90 512 2 /
adjkerntz 148 root txt VREG 0,90 9896 2808973 /sbin/adjkerntz
adjkerntz 148 root txt VREG 0,90 136760 3290906 /libexec/ld-elf.so.1
adjkerntz 148 root txt VREG 0,90 1744432 240771 /lib/libc.so.7
adjkerntz 148 root 0u VCHR 0,26 0t0 26 /dev/null
adjkerntz 148 root 1u VCHR 0,26 0t0 26 /dev/null
adjkerntz 148 root 2u VCHR 0,26 0t0 26 /dev/null
...略...
lsof 6210 daichi cwd VDIR 0,90 1024 481537 /Users/daichi
lsof 6210 daichi rtd VDIR 0,90 512 2 /
lsof 6210 daichi txt VREG 0,90 133728 2086789 /usr/local/sbin/lsof
lsof 6210 daichi txt VREG 0,90 136760 3290906 /libexec/ld-elf.so.1
lsof 6210 daichi txt VREG 0,90 60552 240805 /lib/libkvm.so.7
lsof 6210 daichi txt VREG 0,90 1744432 240771 /lib/libc.so.7
lsof 6210 daichi txt VREG 0,90 97592 240798 /lib/libelf.so.2
lsof 6210 daichi 0u VCHR 0,106 0t329561 106 /dev/pts/0
lsof 6210 daichi 1u VCHR 0,106 0t329561 106 /dev/pts/0
lsof 6210 daichi 2u VCHR 0,106 0t329561 106 /dev/pts/0
lsof 6210 daichi 3r VCHR 0,19 0t0 19 /dev/mem
lsof 6210 daichi 4r VCHR 0,20 0xfffff8001a2e8550 20 /dev/kmem
%
左端の列にプロセス名(コマンド名)、右端の列に開かれているファイルのパスが表示される。
「これでは出力されるものが多すぎて見づらい」というようであれば、awkコマンドを使って必要なものだけを出力させるようにすればよいだろう。
覚えておきたいlsofコマンドの使い方
lsofコマンドでまず覚えておきたいのは、次のように引数にファイルパスを指定する方法だ。
% lsof /dev/null
COMMAND PID USER FD TYPE DEVICE SIZE/OFF NODE NAME
adjkerntz 148 root 0u VCHR 0,26 0t0 26 /dev/null
adjkerntz 148 root 1u VCHR 0,26 0t0 26 /dev/null
adjkerntz 148 root 2u VCHR 0,26 0t0 26 /dev/null
devd 348 root 0u VCHR 0,26 0t0 26 /dev/null
devd 348 root 1u VCHR 0,26 0t0 26 /dev/null
devd 348 root 2u VCHR 0,26 0t0 26 /dev/null
syslogd 492 root 0u VCHR 0,26 0t0 26 /dev/null
syslogd 492 root 1u VCHR 0,26 0t0 26 /dev/null
syslogd 492 root 2u VCHR 0,26 0t0 26 /dev/null
rpcbind 511 root 0u VCHR 0,26 0t0 26 /dev/null
rpcbind 511 root 1u VCHR 0,26 0t0 26 /dev/null
rpcbind 511 root 2u VCHR 0,26 0t0 26 /dev/null
rpc.statd 545 root 0u VCHR 0,26 0t0 26 /dev/null
rpc.statd 545 root 1u VCHR 0,26 0t0 26 /dev/null
rpc.statd 545 root 2u VCHR 0,26 0t0 26 /dev/null
rpc.lockd 548 root 0u VCHR 0,26 0t0 26 /dev/null
rpc.lockd 548 root 1u VCHR 0,26 0t0 26 /dev/null
rpc.lockd 548 root 2u VCHR 0,26 0t0 26 /dev/null
nginx 600 root 0u VCHR 0,26 0t0 26 /dev/null
nginx 600 root 1u VCHR 0,26 0t0 26 /dev/null
nginx 602 daichi 0u VCHR 0,26 0t0 26 /dev/null
nginx 602 daichi 1u VCHR 0,26 0t0 26 /dev/null
sshd 637 root 0u VCHR 0,26 0t0 26 /dev/null
sshd 637 root 1u VCHR 0,26 0t0 26 /dev/null
sshd 637 root 2u VCHR 0,26 0t0 26 /dev/null
sendmail 640 root 0r VCHR 0,26 0t0 26 /dev/null
sendmail 640 root 1w VCHR 0,26 0t0 26 /dev/null
sendmail 640 root 2w VCHR 0,26 0t0 26 /dev/null
sendmail 643 smmsp 0r VCHR 0,26 0t0 26 /dev/null
sendmail 643 smmsp 1w VCHR 0,26 0t0 26 /dev/null
sendmail 643 smmsp 2w VCHR 0,26 0t0 26 /dev/null
cron 647 root 0u VCHR 0,26 0t0 26 /dev/null
cron 647 root 1u VCHR 0,26 0t0 26 /dev/null
cron 647 root 2u VCHR 0,26 0t0 26 /dev/null
autounmou 694 root 0u VCHR 0,26 0t0 26 /dev/null
autounmou 694 root 1u VCHR 0,26 0t0 26 /dev/null
autounmou 694 root 2u VCHR 0,26 0t0 26 /dev/null
automount 699 root 0u VCHR 0,26 0t0 26 /dev/null
automount 699 root 1u VCHR 0,26 0t0 26 /dev/null
automount 699 root 2u VCHR 0,26 0t0 26 /dev/null
sshd 716 root 0r VCHR 0,26 0t0 26 /dev/null
sshd 716 root 1u VCHR 0,26 0t0 26 /dev/null
sshd 716 root 2u VCHR 0,26 0t0 26 /dev/null
sshd 718 daichi 0u VCHR 0,26 0t0 26 /dev/null
sshd 718 daichi 1u VCHR 0,26 0t0 26 /dev/null
sshd 718 daichi 2u VCHR 0,26 0t0 26 /dev/null
ssh-agent 801 daichi 0u VCHR 0,26 0t0 26 /dev/null
ssh-agent 801 daichi 1u VCHR 0,26 0t0 26 /dev/null
ssh-agent 801 daichi 2u VCHR 0,26 0t0 26 /dev/null
sh 5407 daichi 0r VCHR 0,26 0t0 26 /dev/null
sh 5407 daichi 1w VCHR 0,26 0t0 26 /dev/null
sh 5407 daichi 2w VCHR 0,26 0t0 26 /dev/null
nvim 5414 daichi 15r VCHR 0,26 0t0 26 /dev/null
nvim 5414 daichi 22r VCHR 0,26 0t0 26 /dev/null
nvim 5414 daichi 29r VCHR 0,26 0t0 26 /dev/null
ydwait 6273 daichi 0r VCHR 0,26 0t0 26 /dev/null
ydwait 6273 daichi 1w VCHR 0,26 0t0 26 /dev/null
ydwait 6273 daichi 2w VCHR 0,26 0t0 26 /dev/null
nvim 6274 daichi 15r VCHR 0,26 0t0 26 /dev/null
nvim 6274 daichi 22r VCHR 0,26 0t0 26 /dev/null
nvim 6274 daichi 29r VCHR 0,26 0t0 26 /dev/null
%
このようにlsofコマンドを実行した場合、指定したファイルパスにあるファイルを開いているプロセスのみを表示させることができる。調べたいファイルが明らかな場合には、lsofコマンドの引数にそのファイルのパスを指定してコマンドを実装すればよいわけだ。
もう1つ覚えておきたいのが、「+D」というオプションだ。このオプションには、さらに引数としてディレクトリを指定する。すると、指定したディレクトリ以下のファイルを開いているプロセスの一覧を得ることができる。
例えば、ログファイルを保持するために使われることが多い/var/log/ディレクトリを+Dの引数として指定すれば,次のように/var/log/の下にログデータを出力しているプロセスの情報を得ることができる。
% lsof +D /var/log/
COMMAND PID USER FD TYPE DEVICE SIZE/OFF NODE NAME
syslogd 492 root 11w VREG 0,90 98261 884197 /var/log/messages
syslogd 492 root 12w VREG 0,90 59 883315 /var/log/security
syslogd 492 root 13w VREG 0,90 88974 883184 /var/log/auth.log
syslogd 492 root 14w VREG 0,90 1731 885649 /var/log/maillog
syslogd 492 root 15w VREG 0,90 59 883310 /var/log/lpd-errs
syslogd 492 root 16w VREG 0,90 59 883316 /var/log/xferlog
syslogd 492 root 17w VREG 0,90 60101 885116 /var/log/cron
syslogd 492 root 18w VREG 0,90 318 883309 /var/log/debug.log
syslogd 492 root 19w VREG 0,90 59 883313 /var/log/ppp.log
nginx 600 root 2w VREG 0,90 112966 2167621 /var/log/nginx/error.log
nginx 600 root 4w VREG 0,90 3545140 2167622 /var/log/nginx/access.log
nginx 600 root 5w VREG 0,90 112966 2167621 /var/log/nginx/error.log
nginx 602 daichi 2w VREG 0,90 112966 2167621 /var/log/nginx/error.log
nginx 602 daichi 4w VREG 0,90 3545140 2167622 /var/log/nginx/access.log
nginx 602 daichi 5w VREG 0,90 112966 2167621 /var/log/nginx/error.log
%
つまり、どのプロセスがどのファイルにログデータを出力しているのかを調べることができるというわけだ。
lsofコマンドにはさまざまなオプションが用意されているが、基本的にはこの辺りの操作を知っておくだけで、かなり便利に使うことができる。また、lsofコマンドに限らないが、sortコマンドやawkコマンドを使って出力内容を整理できると一層効率が上がる。それらのコマンドの使い方については、既に本連載で取り上げているので、そちらで復習していただきたい。