lsofコマンドでは、前々回で紹介してきたように開かれているファイルと、それを開いているプロセスの情報を取得するだけでなく、オプションを指定したり、ほかのコマンドを併用することで表示されるデータを変更したり、絞り込んだりすることもできる。サーバモニタリングの際にはなにかと重宝するコマンドだ。今回は、その辺りの使い方について解説しよう。
lsofの使い方 - ちょっとした応用
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 18412 root cwd VDIR 0,90 512 2899866 /Users/daichi/Documents/lwt/20170529/commands
lsof 18412 root rtd VDIR 0,90 512 2 /
lsof 18412 root txt VREG 0,90 133728 2086789 /usr/local/sbin/lsof
lsof 18412 root txt VREG 0,90 136760 3290906 /libexec/ld-elf.so.1
lsof 18412 root txt VREG 0,90 60552 240805 /lib/libkvm.so.7
lsof 18412 root txt VREG 0,90 1744432 240771 /lib/libc.so.7
lsof 18412 root txt VREG 0,90 97592 240798 /lib/libelf.so.2
lsof 18412 root 0u VCHR 0,109 0t108478 109 /dev/pts/2
lsof 18412 root 1u VCHR 0,109 0t108478 109 /dev/pts/2
lsof 18412 root 2u VCHR 0,109 0t108478 109 /dev/pts/2
lsof 18412 root 3r VCHR 0,19 0t0 19 /dev/mem
lsof 18412 root 4r VCHR 0,20 0xfffff80003a48280 20 /dev/kmem
lsofコマンドは、「巨大なデータファイルを開いているプロセスを探す」といった目的で使うことがある。上記の出力で言うと、7列目に表示されている「SIZE/OFF(ファイルサイズ)」でソートをかけて、サイズの大きなものから表示させたいところだ。その場合、lsofコマンドと組み合わせてsortコマンドを次のように使えばよい。
% lsof | sort --numeric-sort -k7,7 -r
nginx 602 daichi 4w VREG 0,90 3657866 2167622 /var/log/nginx/access.log
nginx 600 root 4w VREG 0,90 3657866 2167622 /var/log/nginx/access.log
vmtoolsd 142 root txt VREG 0,90 2802048 2329561 /usr/local/lib/libicui18n.so.58.2
sshd 10964 daichi txt VREG 0,90 2529000 240770 /lib/libcrypto.so.8
sshd 10962 root txt VREG 0,90 2529000 240770 /lib/libcrypto.so.8
sshd 637 root txt VREG 0,90 2529000 240770 /lib/libcrypto.so.8
ssh-agent 801 daichi txt VREG 0,90 2529000 240770 /lib/libcrypto.so.8
sendmail 643 smmsp txt VREG 0,90 2529000 240770 /lib/libcrypto.so.8
sendmail 640 root txt VREG 0,90 2529000 240770 /lib/libcrypto.so.8
nginx 602 daichi txt VREG 0,90 2529000 240770 /lib/libcrypto.so.8
nginx 600 root txt VREG 0,90 2529000 240770 /lib/libcrypto.so.8
nvim 18073 daichi txt VREG 0,90 2505328 2410252 /usr/local/bin/nvim
vmtoolsd 142 root txt VREG 0,90 1812440 2332339 /usr/local/lib/libicuuc.so.58.2
ydwait 18625 daichi txt VREG 0,90 1744432 240771 /lib/libc.so.7
vmtoolsd 142 root txt VREG 0,90 1744432 240771 /lib/libc.so.7
syslogd 492 root txt VREG 0,90 1744432 240771 /lib/libc.so.7
sudo 18676 root txt VREG 0,90 1744432 240771 /lib/libc.so.7
sshd 10964 daichi txt VREG 0,90 1744432 240771 /lib/libc.so.7
sshd 10962 root txt VREG 0,90 1744432 240771 /lib/libc.so.7
sshd 637 root txt VREG 0,90 1744432 240771 /lib/libc.so.7
ssh-agent 801 daichi txt VREG 0,90 1744432 240771 /lib/libc.so.7
sh 18066 daichi txt VREG 0,90 1744432 240771 /lib/libc.so.7
sendmail 643 smmsp txt VREG 0,90 1744432 240771 /lib/libc.so.7
sendmail 640 root txt VREG 0,90 1744432 240771 /lib/libc.so.7
rpcbind 511 root txt VREG 0,90 1744432 240771 /lib/libc.so.7
rpc.statd 545 root txt VREG 0,90 1744432 240771 /lib/libc.so.7
rpc.lockd 548 root txt VREG 0,90 1744432 240771 /lib/libc.so.7
nvim 18073 daichi txt VREG 0,90 1744432 240771 /lib/libc.so.7
...略...
ydwait 18736 daichi 7r VREG 0,90 1165 2899873 /Users/daichi/Documents/lwt/20170529/typescript.html
rpc.statd 545 root 3r VREG 0,90 789 2495738 /etc/netconfig
ydwait 18736 daichi 5r VREG 0,90 565 2899865 /Users/daichi/Documents/lwt/20170529/Makefile
ydwait 18736 daichi 6r VREG 0,90 539 2904027 /Users/daichi/Documents/lwt/20170529/typescript.xml
...略...
%
sortコマンドは、オプションとして「—numeric-sort」を指定すると、対象を数字として比較してくれる。これを指定しないと、例えば「10」と「2」では2のほうを大きな値として処理してしまうのだ。「—numeric-sort」をオプションに指定すると、「数字の10」と「数字の2」として比較するようになり、10のほうが大きな値だと認識して処理してくれる。
また、今回はファイルサイズの大きなものほど上位に表示させたいので、「-r」も指定する。これで、サイズの大きな順に表示するようになる。そして、「-k7,7」だ。このオプションで7列目の値(つまりファイルサイズ)をソートの対象としてくれる。「—numeric-sort」を指定したソートは何かと便利なので、これを機に覚えておいてもらえればと思う。
実際にデータを使うとなると、上記の出力では余分なデータが含まれているし、ファイルサイズ以外のデータも表示されている。そこで、次のようにawkコマンドやgrepコマンドを組み合わせると、表示データを絞り込むことができる。
% lsof | awk '{print $1,$7}' |
> sort --numeric-sort -k2,2 -r |
> grep -E ' [0-9]+$'
nginx 3657866
nginx 3657866
sshd 2529000
sshd 2529000
sshd 2529000
ssh-agent 2529000
sendmail 2529000
sendmail 2529000
nginx 2529000
nginx 2529000
nvim 2505328
nvim 2505328
ydwait 1744432
syslogd 1744432
sudo 1744432
sshd 1744432
sshd 1744432
sshd 1744432
ssh-agent 1744432
sh 1744432
sendmail 1744432
sendmail 1744432
...略...
lsof 0
gsort 0
fish 0
fish 0
fish 0
fish 0
awk 0
%
まず、「awk ‘{print $1,$7}’」の処理でデータを1列目と7列目に絞り込むことができる。データが2列になったので、ソートの処理では「sort —numeric-sort -k2,2 -r」と指定して2列目をソートの対象にする。最後に、「grep -E ’ [0-9]+$’」の処理でファイルサイズ以外のデータが表示されている行を除外している。「’ [0-9]+$’」の指定で2列目に数字以外のデータが含まれている行を除外しているのだ。
実際の業務ではこういった処理をスクリプトにまとめておき、一定以上のサイズのファイルが開かれていたり、開かれているファイルの総サイズ数が一定の値を超えたりした場合、管理者に警告のメールを送信するといった処理を組むことになるだろう。後は「crontab(5)」に登録して定期的に実行するようにすれば、管理の手間が1つ減るというわけだ。
こんな感じで何らかのコマンドで必要なデータを含む値を出力させて、ほかのコマンドで出力されたデータを切り貼りし、結果として別の処理を行わせる……というのが、管理を自動化する際の1つのポイントとなる。