- 1 lsofコマンドとは?
- 2 検証環境
- 3 インストール方法
- 4 オプション一覧
- 5 ファイルをオープンしているプロセスを調べる方法
- 6 オープンしているファイルをユーザで絞り込む方法(-u)
- 7 オープンしているファイルをFDで絞り込む方法
- 8 プロセス名の表示幅を広げる方法(+c)
- 9 INETドメインソケットに関する使いかた
- 10 リピートモードの使い方
- 11 ソケットの状態を表示する方法
- Z 参考情報
1 lsofコマンドとは?
ファイルをオープンしているプロセスを表示するコマンドです
2 検証環境
CentOS版数は以下のとおりです。
[root@server ~]# cat /etc/redhat-release CentOS Linux release 7.9.2009 (Core)
カーネル版数は以下のとおりです。
[root@server ~]# uname -r 3.10.0-1160.el7.x86_64
3 インストール方法
lsofパッケージをインストールします。
[root@server ~]# yum -y install lsof
lsof コマンドの版数を確認します。
[root@server ~]# lsof -v lsof version information: revision: 4.87
4 オプション一覧
[root@server ~]# lsof -h lsof 4.87 latest revision: ftp://lsof.itap.purdue.edu/pub/tools/unix/lsof/ latest FAQ: ftp://lsof.itap.purdue.edu/pub/tools/unix/lsof/FAQ latest man page: ftp://lsof.itap.purdue.edu/pub/tools/unix/lsof/lsof_man usage: [-?abhKlnNoOPRtUvVX] [+|-c c] [+|-d s] [+D D] [+|-f[gG]] [+|-e s] [-F [f]] [-g [s]] [-i [i]] [+|-L [l]] [+m [m]] [+|-M] [-o [o]] [-p s] [+|-r [t]] [-s [p:s]] [-S [t]] [-T [t]] [-u s] [+|-w] [-x [fl]] [-Z [Z]] [--] [names] Defaults in parentheses; comma-separated set (s) items; dash-separated ranges. -?|-h list help -a AND selections (OR) -b avoid kernel blocks -c c cmd c ^c /c/[bix] +c w COMMAND width (9) +d s dir s files -d s select by FD set +D D dir D tree *SLOW?* +|-e s exempt s *RISKY* -i select IPv[46] files -K list tasKs (threads) -l list UID numbers -n no host names -N select NFS files -o list file offset -O no overhead *RISKY* -P no port names -R list paRent PID -s list file size -t terse listing -T disable TCP/TPI info -U select Unix socket -v list version info -V verbose search +|-w Warnings (+) -X skip TCP&UDP* files -Z Z context [Z] -- end option scan +f|-f +filesystem or -file names +|-f[gG] flaGs -F [f] select fields; -F? for help +|-L [l] list (+) suppress (-) link counts < l (0 = all; default = 0) +m [m] use|create mount supplement +|-M portMap registration (-) -o o o 0t offset digits (8) -p s exclude(^)|select PIDs -S [t] t second stat timeout (15) -T qs TCP/TPI Q,St (s) info -g [s] exclude(^)|select and print process group IDs -i i select by IPv[46] address: [46][proto][@host|addr][:svc_list|port_list] +|-r [t[m<fmt>]] repeat every t seconds (15); + until no files, - forever. An optional suffix to t is m<fmt>; m must separate t from <fmt> and <fmt> is an strftime(3) format for the marker line. -s p:s exclude(^)|select protocol (p = TCP|UDP) states by name(s). -u s exclude(^)|select login|UID set s -x [fl] cross over +d|+D File systems or symbolic Links names select named files or files on named file systems Anyone can list all files; /dev warnings disabled; kernel ID check disabled.
5 ファイルをオープンしているプロセスを調べる方法
5.1 基本的な使い方
/var/log/messagesファイルに対して、lsofコマンドを実行してみます。 abrt-watch-logとrsyslogdの2つのプロセスが/var/log/messagesファイルをオープンしていることがわかります。 なお、プロセス名(COMMAND)の長さは、デフォルトで9文字です。そのため、abrt-watch-logがabrt-watcと切り詰められています。
[root@server ~]# lsof /var/log/messages COMMAND PID USER FD TYPE DEVICE SIZE/OFF NODE NAME abrt-watc 643 root 4r REG 8,3 330928 16878700 /var/log/messages rsyslogd 1074 root 4w REG 8,3 330928 16878700 /var/log/messages
次に、rsyslogサービスを停止します。
[root@server ~]# systemctl stop rsyslog.service
再度、lsofコマンドを実行します。 rsyslogdプロセスは、/var/log/messagesをオープンしていないことがわかります。
[root@server ~]# lsof /var/log/messages COMMAND PID USER FD TYPE DEVICE SIZE/OFF NODE NAME abrt-watc 643 root 4r REG 8,3 330928 16878700 /var/log/messages
5.2 ディレクトリを再帰的にたどる方法(+D)
+Dオプションを指定すると、指定したディレクト配下を再帰的にたどり、ファイルをオープンしているプロセスを表示します。
[root@server ~]# lsof +D /var/log/ COMMAND PID USER FD TYPE DEVICE SIZE/OFF NODE NAME auditd 598 root 5w REG 8,3 2245418 33584848 /var/log/audit/audit.log abrt-watc 643 root 4r REG 8,3 337295 16878700 /var/log/messages firewalld 745 root 3w REG 8,3 6449 17913092 /var/log/firewalld tuned 1073 root 3w REG 8,3 16740 51319417 /var/log/tuned/tuned.log cupsd 1079 root 6u REG 8,3 0 51184781 /var/log/cups/access_log cupsd 1079 root 7u REG 8,3 0 51184782 /var/log/cups/error_log cupsd 1079 root 8u REG 8,3 0 51184783 /var/log/cups/page_log rsyslogd 3327 root 6w REG 8,3 337295 16878700 /var/log/messages rsyslogd 3327 root 7w REG 8,3 5134 16878701 /var/log/secure rsyslogd 3327 root 8w REG 8,3 4706 16878698 /var/log/cron
5.3 ディレクトリを再帰的にたどらない方法(+d)
+dオプションを指定すると、指定したディレクトに存在するファイルをオープンしているプロセスを表示します。
[root@server ~]# lsof +d /var/log/ COMMAND PID USER FD TYPE DEVICE SIZE/OFF NODE NAME abrt-watc 643 root 4r REG 8,3 337499 16878700 /var/log/messages firewalld 745 root 3w REG 8,3 6449 17913092 /var/log/firewalld rsyslogd 3327 root 6w REG 8,3 337499 16878700 /var/log/messages rsyslogd 3327 root 7w REG 8,3 5134 16878701 /var/log/secure rsyslogd 3327 root 8w REG 8,3 4706 16878698 /var/log/cron
6 オープンしているファイルをユーザで絞り込む方法(-u)
6.1 特定のユーザが使用しているファイルを表示する方法
chronyユーザがオープンしているファイルを表示してみます。
[root@server ~]# lsof -u chrony COMMAND PID USER FD TYPE DEVICE SIZE/OFF NODE NAME chronyd 667 chrony cwd DIR 8,3 264 64 / chronyd 667 chrony rtd DIR 8,3 264 64 / chronyd 667 chrony txt REG 8,3 269392 461392 /usr/sbin/chronyd -snip-
次に、polkitdユーザがオープンしているファイルを表示してみます。
[root@server ~]# lsof -u polkitd COMMAND PID USER FD TYPE DEVICE SIZE/OFF NODE NAME polkitd 627 polkitd cwd DIR 8,3 264 64 / polkitd 627 polkitd rtd DIR 8,3 264 64 / polkitd 627 polkitd txt REG 8,3 120432 34158507 /usr/lib/polkit-1/polkitd -snip-
6.2 特定のユーザ以外のユーザが使用しているファイルを表示する方法
rootユーザ以外のユーザがオープンしているファイルを表示してみます。
[root@server ~]# lsof -u ^root COMMAND PID TID USER FD TYPE DEVICE SIZE/OFF NODE NAME lsmd 625 libstoragemgmt cwd DIR 8,3 264 64 / lsmd 625 libstoragemgmt rtd DIR 8,3 264 64 / lsmd 625 libstoragemgmt txt REG 8,3 24016 56028264 /usr/bin/lsmd -snip-
7 オープンしているファイルをFDで絞り込む方法
chronyユーザがオープンしているファイルの中で、FD=8のファイルを表示してみます。 -uでユーザを指定し、-dでFD(File Descriptor)を指定します。-aは-uと-dのAND条件を指定するために使用しています。 lsofの実行結果より、chronyユーザは、/var/run/chrony/chronyd.sockをFD=8でオープンしていることがわかります。
[root@server ~]# lsof -u chrony -a -d 8 COMMAND PID USER FD TYPE DEVICE SIZE/OFF NODE NAME chronyd 667 chrony 8u unix 0xffff9e0bf5790440 0t0 20186 /var/run/chrony/chronyd.sock
8 プロセス名の表示幅を広げる方法(+c)
lsofの実行結果に表示されるプロセス名(COMMAND)の幅はデフォルトで9文字です。 +cオプションを指定することで、幅を広げることができます。
+c0を指定すると、プロセス名が途中で切り捨てられることなく全て表示されます。
[root@server ~]# lsof +c0 /var/log/messages COMMAND PID USER FD TYPE DEVICE SIZE/OFF NODE NAME abrt-watch-log 643 root 4r REG 8,3 340736 16878700 /var/log/messages rsyslogd 3327 root 6w REG 8,3 340736 16878700 /var/log/messages
次に、+c10を指定してみます。 abrt-watch-logプロセス名がデフォルト表示のabrt-watcからabrt-watchに1文字多く表示されるようになったことがわかります。
[root@server ~]# lsof +c10 /var/log/messages COMMAND PID USER FD TYPE DEVICE SIZE/OFF NODE NAME abrt-watch 643 root 4r REG 8,3 340869 16878700 /var/log/messages rsyslogd 3327 root 6w REG 8,3 340869 16878700 /var/log/messages
9 INETドメインソケットに関する使いかた
9.1 IPV4,IPv6ソケットを使用しているプロセスを絞り込む方法(-i)
-iオプションを使うと、IPV4,IPv6ソケットを使用しているプロセスを表示できます。 rpcbindプロセスは、IPV4,IPv6ソケットを使用していることがわかります。
[root@server ~]# lsof -i COMMAND PID USER FD TYPE DEVICE SIZE/OFF NODE NAME rpcbind 624 rpc 6u IPv4 19549 0t0 UDP *:sunrpc rpcbind 624 rpc 7u IPv4 19550 0t0 UDP *:798 rpcbind 624 rpc 8u IPv4 19551 0t0 TCP *:sunrpc (LISTEN) rpcbind 624 rpc 9u IPv6 19552 0t0 UDP *:sunrpc rpcbind 624 rpc 10u IPv6 19553 0t0 UDP *:798 rpcbind 624 rpc 11u IPv6 19554 0t0 TCP *:sunrpc (LISTEN) -snip-
9.2 TCPソケットを使用しているプロセスを絞り込む方法(-i)
-iまたはiTCPとオプションを指定することで、TCPのソケットを使用しているプロセスを表示することができます。
[root@server ~]# lsof -iTCP COMMAND PID USER FD TYPE DEVICE SIZE/OFF NODE NAME rpcbind 624 rpc 8u IPv4 19551 0t0 TCP *:sunrpc (LISTEN) rpcbind 624 rpc 11u IPv6 19554 0t0 TCP *:sunrpc (LISTEN) sshd 1040 root 3u IPv4 25400 0t0 TCP *:ssh (LISTEN) sshd 1040 root 4u IPv6 25402 0t0 TCP *:ssh (LISTEN) cupsd 1043 root 10u IPv6 25413 0t0 TCP localhost:ipp (LISTEN) cupsd 1043 root 11u IPv4 25414 0t0 TCP localhost:ipp (LISTEN) master 1344 root 13u IPv4 27774 0t0 TCP localhost:smtp (LISTEN) master 1344 root 14u IPv6 27775 0t0 TCP localhost:smtp (LISTEN) dnsmasq 1399 nobody 6u IPv4 23540 0t0 TCP server:domain (LISTEN) sshd 1708 root 3u IPv4 28102 0t0 TCP server:ssh->DESKTOP-MB6G4KI:53893 (ESTABLISHED)
9.3 UDPソケットを使用しているプロセスを絞り込む方法(-iUDP)
-iUDPとオプションを指定することで、UDPのソケットを使用しているプロセスを表示することができます。
[root@server ~]# lsof -iUDP COMMAND PID USER FD TYPE DEVICE SIZE/OFF NODE NAME rpcbind 624 rpc 6u IPv4 19549 0t0 UDP *:sunrpc rpcbind 624 rpc 7u IPv4 19550 0t0 UDP *:798 rpcbind 624 rpc 9u IPv6 19552 0t0 UDP *:sunrpc rpcbind 624 rpc 10u IPv6 19553 0t0 UDP *:798 avahi-dae 647 avahi 12u IPv4 20389 0t0 UDP *:mdns avahi-dae 647 avahi 13u IPv4 20390 0t0 UDP *:51640 chronyd 678 chrony 5u IPv4 23578 0t0 UDP localhost:323 chronyd 678 chrony 6u IPv6 23579 0t0 UDP localhost:323 dhclient 849 root 6u IPv4 22863 0t0 UDP *:bootpc dnsmasq 1399 nobody 3u IPv4 23536 0t0 UDP *:bootps dnsmasq 1399 nobody 5u IPv4 23539 0t0 UDP server:domain
9.4 ポート番号で使用しているプロセスを絞り込む方法
TCPの22番ポートを使用しているプロセスを表示してます。 sshdプロセスがTCPの22番ポートを使用していることがわかります。 なお、-Pオプションを指定すると、sshのようなサービス名ではなくポート番号を表示することができます。
[root@server ~]# lsof -i:22 -P COMMAND PID USER FD TYPE DEVICE SIZE/OFF NODE NAME sshd 1092 root 3u IPv4 27698 0t0 TCP *:22 (LISTEN) sshd 1092 root 4u IPv6 27700 0t0 TCP *:22 (LISTEN) sshd 1801 root 3u IPv4 28373 0t0 TCP server:22->DESKTOP-MB6G4KI:60395 (ESTABLISHED)
ポート番号の範囲を指定することもできます。 TCPの1番ポートから50番ポートを使用しているプロセスを表示してみます。
[root@server ~]# lsof -i:1-50 -P COMMAND PID USER FD TYPE DEVICE SIZE/OFF NODE NAME sshd 1092 root 3u IPv4 27698 0t0 TCP *:22 (LISTEN) sshd 1092 root 4u IPv6 27700 0t0 TCP *:22 (LISTEN) master 1309 root 13u IPv4 28815 0t0 TCP localhost:25 (LISTEN) master 1309 root 14u IPv6 28816 0t0 TCP localhost:25 (LISTEN) sshd 1801 root 3u IPv4 28373 0t0 TCP server:22->DESKTOP-MB6G4KI:60395 (ESTABLISHED)
9.5 IPアドレスでプロセスを絞り込む方法
[root@server ~]# lsof -i@192.168.2.100 -n COMMAND PID USER FD TYPE DEVICE SIZE/OFF NODE NAME sshd 1801 root 3u IPv4 28373 0t0 TCP 192.168.2.100:ssh->192.168.2.12:60395 (ESTABLISHED)
9.6 TCPの状態でプロセスを絞り込む方法
TCPの状態がESTABLISHEDのプロセスを表示してみます。
[root@server ~]# lsof -i -sTCP:ESTABLISHED -n COMMAND PID USER FD TYPE DEVICE SIZE/OFF NODE NAME sshd 1801 root 3u IPv4 28373 0t0 TCP 192.168.2.100:ssh->192.168.2.12:60395 (ESTABLISHED)
次は、TCPの状態がLISTENのプロセスを表示してみます。
[root@server ~]# lsof -i -sTCP:LISTEN -n COMMAND PID USER FD TYPE DEVICE SIZE/OFF NODE NAME rpcbind 647 rpc 8u IPv4 20029 0t0 TCP *:sunrpc (LISTEN) rpcbind 647 rpc 11u IPv6 20032 0t0 TCP *:sunrpc (LISTEN) cupsd 1085 root 10u IPv6 28744 0t0 TCP [::1]:ipp (LISTEN) cupsd 1085 root 11u IPv4 28745 0t0 TCP 127.0.0.1:ipp (LISTEN) sshd 1092 root 3u IPv4 27698 0t0 TCP *:ssh (LISTEN) sshd 1092 root 4u IPv6 27700 0t0 TCP *:ssh (LISTEN) master 1309 root 13u IPv4 28815 0t0 TCP 127.0.0.1:smtp (LISTEN) master 1309 root 14u IPv6 28816 0t0 TCP [::1]:smtp (LISTEN) dnsmasq 1714 nobody 6u IPv4 28089 0t0 TCP 192.168.122.1:domain (LISTEN)
10 リピートモードの使い方
ncプロセス(-c)が使用するINETドメイン(-i)のソケットを2秒間隔(-r2)で監視してみます。 -mはマーカです。%Tは時刻を表示します。 また、-aオプションを使って3つの条件をAND条件で指定しています。
lsofコマンドを実行します。 なお、ncコマンドの使い方は、ncコマンドの使い方(ネットワーク実験の幅が広がるなぁ~) - hana_shinのLinux技術ブログを参照してくだい。
[root@server ~]# lsof -c nc -a -i4 -a -P -a -r2m====%T==== ====17:06:14==== ====17:06:16====
もう1つターミナルを開きます。そしてncコマンドを実行します。
[root@server ~]# nc -kl 11111
lsofコマンドの実行結果を確認します。 ncプロセスのTCPの状態がLISTENになったことがわかります。
[root@server ~]# lsof -c nc -a -i4 -a -P -a -r2m====%T==== ====17:08:50==== ====17:08:52==== ====17:08:54==== ====17:08:56==== COMMAND PID USER FD TYPE DEVICE SIZE/OFF NODE NAME nc 3500 root 4u IPv4 46030 0t0 TCP *:11111 (LISTEN) ====17:08:58==== COMMAND PID USER FD TYPE DEVICE SIZE/OFF NODE NAME nc 3500 root 4u IPv4 46030 0t0 TCP *:11111 (LISTEN) -snip-
クライアントでncコマンドを実行します。
[root@client ~]# nc 192.168.2.100 11111
lsofコマンドの実行結果を確認します。 ncプロセスのTCPの状態がLISTENからESTABLISHEDになったことがわかります。
[root@server ~]# lsof -c nc -a -i4 -a -P -a -r2m====%T==== -snip- ====17:11:25==== COMMAND PID USER FD TYPE DEVICE SIZE/OFF NODE NAME nc 3500 root 4u IPv4 46030 0t0 TCP *:11111 (LISTEN) nc 3500 root 5u IPv4 56384 0t0 TCP server:11111->client:43798 (ESTABLISHED)
11 ソケットの状態を表示する方法
[root@server ~]# lsof -i4TCP -Tqs COMMAND PID USER FD TYPE DEVICE SIZE/OFF NODE NAME rpcbind 647 rpc 8u IPv4 20029 0t0 TCP *:sunrpc (LISTEN QR=0 QS=0) cupsd 1085 root 11u IPv4 28745 0t0 TCP localhost:ipp (LISTEN QR=0 QS=0) sshd 1092 root 3u IPv4 27698 0t0 TCP *:ssh (LISTEN QR=0 QS=0) master 1309 root 13u IPv4 28815 0t0 TCP localhost:smtp (LISTEN QR=0 QS=0) dnsmasq 1714 nobody 6u IPv4 28089 0t0 TCP server:domain (LISTEN QR=0 QS=0) sshd 1801 root 3u IPv4 28373 0t0 TCP server:ssh->DESKTOP-MB6G4KI:60395 (ESTABLISHED QR=0 QS=36)
なお、上記実行結果中のQR、QSの意味は以下のとおりです。
QR:カーネル受信バッファに存在する受信データのバイト数。ユーザプロセスがまだ読み出していない受信データです。
QS:カーネル送信バッファに存在する送信データのバイト数。まだACKを受信しておらず、開放されていない送信データです。
QRについて、以下のような実験をして確認してみます。 まず、サーバでncコマンドを実行します。
[root@server ~]# nc -kl 11111
lsofコマンドを実行します。QRの値は0であることがわかります。
[root@server ~]# lsof -c nc -i4TCP -a -P -a -Tqs COMMAND PID USER FD TYPE DEVICE SIZE/OFF NODE NAME nc 3683 root 4u IPv4 56710 0t0 TCP *:11111 (LISTEN QR=0 QS=0)
クライアントでncコマンドを実行します。 ncコマンドを実行すると、サーバのncプロセスとの間でTCPコネクションが確立されます。
[root@client ~]# nc 192.168.2.100 11111
サーバでCtrl+zを押下して、ncプロセスを停止します。
[root@server ~]# nc -kl 11111 ^Z [1]+ 停止 nc -kl 11111
クライアントで12345と入力します。改行コードも含めて6バイトがサーバに送信されます。
[root@client ~]# nc 192.168.2.100 11111 12345
lsofコマンドを実行します。QRの値が6になったことがわかります。
[root@server ~]# lsof -c nc -i4TCP -a -P -a -Tqs COMMAND PID USER FD TYPE DEVICE SIZE/OFF NODE NAME nc 3683 root 4u IPv4 56710 0t0 TCP *:11111 (LISTEN QR=0 QS=0) nc 3683 root 5u IPv4 58859 0t0 TCP server:11111->client:43806 (ESTABLISHED QR=6 QS=0)
次にfgコマンドを実行して、サーバのncプロセスを再開します。 ncプロセスが再開すると、カーネルの受信バッファから受信データを読み出します。
[root@server ~]# fg nc -kl 11111 12345
再度、lsofコマンドを実行します。QRの値が0になったことがわかります。 これは、ncプロセスを再開したことで、ncプロセスがカーネル受信バッファにたまっていた6バイトのデータを読み出したからです。
[root@server ~]# lsof -c nc -i4TCP -a -P -a -Tqs COMMAND PID USER FD TYPE DEVICE SIZE/OFF NODE NAME nc 3683 root 4u IPv4 56710 0t0 TCP *:11111 (LISTEN QR=0 QS=0) nc 3683 root 5u IPv4 58859 0t0 TCP server:11111->client:43806 (ESTABLISHED QR=0 QS=0)
Z 参考情報
私が業務や記事執筆で参考にした書籍を以下のページに記載します。 Linux技術のスキルアップをしよう! - hana_shinのLinux技術ブログ