lsof

Table of Contents

1. lsof

lsof 是 Unix 调试的瑞士军刀,它是 list open files 的缩写。

不带任何参数运行 lsof 会列出所有进程打开的所有文件。

$ lsof
$ sudo lsof         # 使用 sudo 后,会得到更多的输出

2. lsof 实例

2.1. 查找某文件被哪个进程打开

只需要指定文件的路径, lsof 就会列出所有使用这个文件的进程。你也可以同时指定多个文件, lsof 会列出所有使用这些文件的进程:

$ sudo lsof /path/to/file1  /path/to/file2

比如,查看哪个进程在使用 /usr/bin/python3.6:

$ sudo lsof /usr/bin/python3.6
COMMAND     PID   USER  FD   TYPE DEVICE SIZE/OFF   NODE NAME
networkd-  1012   root txt    REG  252,1  4526456 393952 /usr/bin/python3.6
unattende  1255   root txt    REG  252,1  4526456 393952 /usr/bin/python3.6
python3   31233 ubuntu txt    REG  252,1  4526456 393952 /usr/bin/python3.6
python3   31237 ubuntu txt    REG  252,1  4526456 393952 /usr/bin/python3.6

2.2. 查找进程打开的所有文件(-p, -c)

lsof 指定 -p pid1,pid2 可以列出由某个(或某几个)PID 对应的进程打开的所有文件。如列出进程 450 或 980 打开的文件:

$ lsof -p 450,980

lsof 指定 -c cmd 可以列出可执行文件前缀为 cmd 的进程打开的文件。如列出以 apache 开头的进程打开的文件:

$ lsof -c apache

-c 可以指定多次,如列出所有由 apache 或者 python 开头的进程的打开的文件:

$ lsof -c apache -c python

2.3. 列出网络连接(-i)

lsof 指定 -i 选项可以列出所有打开了网络套接字(TCP 和 UDP)的进程:

$ sudo lsof -i

2.3.1. 列出 TCP 连接

列出 TCP 连接:

$ sudo lsof -i tcp
$ sudo lsof -n -i tcp                 # 直接显示 ip,不显示主机名,这样执行更快
$ sudo lsof -n -i tcp -s tcp:listen   # 仅列出处于 listen 状态的 tcp 连接

2.3.2. 列出使用某端口的进程

列出占用 TCP 或 UDP 的 9000 端口的进程:

$ sudo lsof -i :9000
COMMAND   PID     USER   FD   TYPE     DEVICE SIZE/OFF NODE NAME
nginx    2893     root   17u  IPv4 2094829349      0t0  TCP *:9000 (LISTEN)
nginx   22484 www-data   17u  IPv4 2094829349      0t0  TCP *:9000 (LISTEN)
nginx   22485 www-data   17u  IPv4 2094829349      0t0  TCP *:9000 (LISTEN)

列出占用 TCP 的 9000 端口的进程:

$ sudo lsof -i tcp:9000
COMMAND   PID     USER   FD   TYPE     DEVICE SIZE/OFF NODE NAME
nginx    2893     root   17u  IPv4 2094829349      0t0  TCP *:9000 (LISTEN)
nginx   22484 www-data   17u  IPv4 2094829349      0t0  TCP *:9000 (LISTEN)
nginx   22485 www-data   17u  IPv4 2094829349      0t0  TCP *:9000 (LISTEN)

2.4. 技巧:让输出只包含 PID(-t)

lsof-t 选项表示 terse output,即简洁的输出,其输出中只会包含进程的 PID,以方便通过管道传给其它命令(如 kill)。

比如,找到使用网络的所有进程:

$ lsof -i -t                   # 如果用 sudo,则会有更多的输出
25387
31233

上面输出中只包含 PID,所以很方便用管道做进一步处理,如查看进程详情:

$ lsof -i -t | xargs ps
  PID TTY      STAT   TIME COMMAND
25387 ?        Sl   417:59 /home/ubuntu/jdk-11.0.1/bin/java -Djava.util.logging.config.file=/home/ub
31233 pts/1    S+     0:00 python3 test.py

Author: cig01

Created: <2015-11-22 Sun>

Last updated: <2020-05-10 Sun>

Creator: Emacs 27.1 (Org mode 9.4)