FAIRYFAR-INTERNAL
 
  FAIRYFAR-INTERNAL  |  SITEMAP  |  ABOUT-ME  |  HOME  
您的足迹: Linux下lsof命令详解
Linux下lsof命令详解

lsof(list open files)是一个列出当前系统打开文件的工具。在linux环境下,任何事物都以文件的形式存在,通过文件不仅仅可以访问常规数据,还可以访问网络连接和硬件。所以如传输控制协议(TCP)和用户数据报协议(UDP)套接字等,系统在后台都为该应用程序分配了一个文件描述符,无论这个文件的本质如何,该文件描述符为应用程序与基础操作系统之间的交互提供了通用接口。因为应用程序打开文件的描述符列表提供了大量关于这个应用程序本身的信息,因此通过lsof工具能够查看这个列表对系统监测以及排错将是很有帮助的。

安装

lsof 命令可能没有安装,Redhat安装方法:

yum install lsof

列出所有打开的文件

不带任何参数执行 lsof 命令会输出当前所有活跃进程打开的所有文件:

snippet.bash
[yz@localhost ~]$ lsof | less
COMMAND     PID   TID           USER   FD      TYPE             DEVICE  SIZE/OFF      NODE NAME
systemd       1                 root  cwd   unknown                                        /proc/1/cwd (readlink: Permission denied)
systemd       1                 root  rtd   unknown                                        /proc/1/root (readlink: Permission denied)
systemd       1                 root  txt   unknown                                        /proc/1/exe (readlink: Permission denied)
systemd       1                 root NOFD                                                  /proc/1/fd (opendir: Permission denied)
kthreadd      2                 root  cwd   unknown                                        /proc/2/cwd (readlink: Permission denied)
kthreadd      2                 root  rtd   unknown                                        /proc/2/root (readlink: Permission denied)

其中列 COMMANDPIDUSER 分别表示进程名、进程ID、所属用户。

FD 是文件描述符,下面是可能的类型以及说明

FD 说明
:–: :———-:
cwd 当前目录
txt txt文件
rtd root目录
mem 内存映射文件

TYPE 是文件类型,下面是可能的值以及说明

TYPE 说明
:—–: :—————-:
DIR 目录
REG 普通文件
CHR 字符
a_inode Inode文件
FIFO 管道或者socket文件
netlink 网络
unknown 未知

DEVICE 表示设备ID

SIZE/OFF 表示进程大小

NODE 表示文件的Inode号

NAME 表示路径或者链接

列出指定用户已打开的文件

使用 -u 选项可以列出指定用户已经打开的文件,该选项后面可以接多个用户名,每个用户名之间用空格隔开,表示列出所有指定用户已打开的所有文件。

snippet.bash
[yz@localhost ~]$ lsof -u yz
COMMAND    PID USER   FD      TYPE             DEVICE  SIZE/OFF      NODE NAME
sshd      2805   yz  cwd   unknown                                        /proc/2805/cwd (readlink: Permission denied)
sshd      2805   yz  rtd   unknown                                        /proc/2805/root (readlink: Permission denied)
sshd      2805   yz  txt   unknown                                        /proc/2805/exe (readlink: Permission denied)
sshd      2805   yz NOFD                                                  /proc/2805/fd (opendir: Permission denied)

如果要排除指定用户已经打开的文件,可以在用户名前加 ^ 符号,下面的命令会列出除yz用户外其他所有用户已打开了的文件。

lsof -u ^yz

找出打开着但已被删除了的文件

[yz@localhost ~]$ lsof -u yz | grep deleted
vim     27813   yz    4u   REG  253,1    12288 131167 /home/yz/.p.txt.swp(deleted)

列出所有打开了的网络文件

snippet.bash
[yz@localhost ~]$ lsof -i
COMMAND    PID USER   FD   TYPE  DEVICE SIZE/OFF NODE NAME
node     10444   yz   27u  IPv4 1356954      0t0  TCP localhost:45393->localhost:36542 (ESTABLISHED)
postgres 17442   yz    5u  IPv6  824828      0t0  TCP localhost:7404 (LISTEN)
postgres 17442   yz    6u  IPv4  824829      0t0  TCP localhost:7404 (LISTEN)
postgres 17442   yz    8u  IPv6  824834      0t0  UDP localhost:37288->localhost:37288
  • 列出所有 IPV4/6 网络文件

列出所有已经打开了的 ipv4 网络文件:

snippet.bash
[yz@localhost ~]$ lsof -i 4
COMMAND    PID USER   FD   TYPE  DEVICE SIZE/OFF NODE NAME
node     10444   yz   27u  IPv4 1356954      0t0  TCP localhost:45393->localhost:36542 (ESTABLISHED)
postgres 17442   yz    6u  IPv4  824829      0t0  TCP localhost:7404 (LISTEN)
node     24258   yz   18u  IPv4  848159      0t0  TCP localhost:45393 (LISTEN)
node     24258   yz   21u  IPv4 1353624      0t0  TCP localhost:45393->localhost:36540 (ESTABLISHED)
node     24258   yz   23u  IPv4 1353553      0t0  TCP localhost:45393->localhost:36532 (ESTABLISHED)
node     24352   yz   23u  IPv4 1353556      0t0  TCP localhost:45393->localhost:36534 (ESTABLISHED)

所有已经打开了的 ipv6 网络文件:

snippet.bash
[yz@localhost ~]$ lsof -i 6
COMMAND    PID USER   FD   TYPE DEVICE SIZE/OFF NODE NAME
postgres 17442   yz    5u  IPv6 824828      0t0  TCP localhost:7404 (LISTEN)
postgres 17442   yz    8u  IPv6 824834      0t0  UDP localhost:37288->localhost:37288
postgres 17444   yz    8u  IPv6 824834      0t0  UDP localhost:37288->localhost:37288
postgres 17445   yz    8u  IPv6 824834      0t0  UDP localhost:37288->localhost:37288
  • 列出在指定端口上打开的文件

使用 lsof -i:端口号 可以获得所有在指定端口号上打开的文件。

snippet.bash
[yz@localhost ~]$ lsof -i:7404
COMMAND    PID USER   FD   TYPE DEVICE SIZE/OFF NODE NAME
postgres 17442   yz    5u  IPv6 824828      0t0  TCP localhost:7404 (LISTEN)
postgres 17442   yz    6u  IPv4 824829      0t0  TCP localhost:7404 (LISTEN)

上面例子列出了所有在7404号端口上打开的文件。

在服务器开发中,经常会部署一个网关或者代理程序,用来和客户端通讯,网关或者代理程序需要开放一个固定的端口供客户端连接用。

如果客户端连接不上网关或者代理程序,我们可以用上述命令检查网关或代理程序的端口是否开启,来排除因为端口关闭了导致连接不上网关的情况。

  • 列出使用了指定协议(TCP/UDP) 的文件

使用 lsof -i TCP/UDP 列出使用了TCP 或 UDP 协议的文件。

snippet.bash
[yz@localhost ~]$ lsof -i TCP
COMMAND    PID USER   FD   TYPE  DEVICE SIZE/OFF NODE NAME
node     10444   yz   27u  IPv4 1356954      0t0  TCP localhost:45393->localhost:36542 (ESTABLISHED)
postgres 17442   yz    5u  IPv6  824828      0t0  TCP localhost:7404 (LISTEN)
postgres 17442   yz    6u  IPv4  824829      0t0  TCP localhost:7404 (LISTEN)
node     24258   yz   18u  IPv4  848159      0t0  TCP localhost:45393 (LISTEN)
node     24258   yz   21u  IPv4 1353624      0t0  TCP localhost:45393->localhost:36540 (ESTABLISHED)
node     24258   yz   23u  IPv4 1353553      0t0  TCP localhost:45393->localhost:36532 (ESTABLISHED)
node     24352   yz   23u  IPv4 1353556      0t0  TCP localhost:45393->localhost:36534 (ESTABLISHED)

使用 lsof -i TCP:7404 列出使用了TCP 协议并且端口为7404的文件。

使用 lsof -i TCP:1-7404 列出使用了TCP协议并且端口范围为 1 到 7404 的文件。

snippet.bash
[yz@localhost ~]$ lsof -i TCP:1-7404
COMMAND    PID USER   FD   TYPE DEVICE SIZE/OFF NODE NAME
postgres 17442   yz    5u  IPv6 824828      0t0  TCP localhost:7404 (LISTEN)
postgres 17442   yz    6u  IPv4 824829      0t0  TCP localhost:7404 (LISTEN)

列出目录中所有打开的文件

可以使用lsof命令列出指定目录中的所有打开文件。

现有一个data目录 ,结构如下:

snippet.bash
[yz@localhost ~]$ tree ~/test
/home/yz/test
└── git_demo
    └── Readme.txt
 
1 directory, 1 file

列出 data 目录中打开的文件:

snippet.bash
[yz@localhost ~]$ lsof +D ~/test
COMMAND   PID USER   FD   TYPE DEVICE SIZE/OFF      NODE NAME
vim     29235   yz    4u   REG  253,2    12288 274648855 /home/yz/test/git_demo/.Readme.txt.swp
 
[yz@localhost ~]$ lsof +d ~/test

上面例子中,+D+d 选项都是列出目录中打开的文件。

+D 选项会列出一个目录和其子目录中打开的文件,而 +d 选项只会列出当前目录下已打开的文件。

列出指定进程ID打开的文件

进程ID是操作系统进程的唯一标识,以下命令列出了进程ID为 17442 相关的文件, 从结果中可以知道这个进程ID对应的进程是PostgreSQL。

snippet.bash
[yz@localhost ~]$ ps ux | grep postgresql
yz        1612  0.0  0.0 112728   996 pts/2    S+   15:39   0:00 grep --color=auto postgresql
yz       17442  0.0  0.1 272944 13308 ?        Ss   01:16   0:01 /home/yz/postgresql/pg_bin/bin/postgres -D /home/yz/postgresql/pg_data
 
[yz@localhost ~]$ lsof -p 17442
COMMAND    PID USER   FD   TYPE             DEVICE  SIZE/OFF      NODE NAME
postgres 17442   yz  cwd    DIR              253,2      4096 268882575 /home/yz/postgresql/pg_data
postgres 17442   yz  rtd    DIR              253,0       244        64 /
postgres 17442   yz  txt    REG              253,2  51299336 135847173 /home/yz/postgresql/pg_bin/bin/postgres
postgres 17442   yz  mem    REG              253,0     61624  33644885 /usr/lib64/libnss_files-2.17.so
……

上述命令中,-p 选项后面可以指定多个进程ID,每个进程ID之间用逗号分隔,如果想排除掉某个进程打开的文件,可以在该进程ID前面加上 ^符号。

lsof -p 1,2,3,^4

上述命令会列出进程1,进程2,进程3打开的所有文件,同时忽略进程4打开的文件。

杀死指定用户的所有进程

前面介绍了列出指定用户所有打开的文件,我们可以组合 kill 命令一起使用,实现杀死指定用户的所有进程的功能,具体的命令如下:

kill -9 `lsof -t -u yz`

上述命令中,lsof -u yz 是列出yz用户所有打开的文件,加上 -t 选项之后表示结果只列出PID列,也就是进程ID列,其他列都忽略,前面的 kill -9 表示强制结束指定的进程ID。

小结

本文介绍了 lsof 命令的一些常见用法,它还有很多其他的用法,请自行查看man文档。



打赏作者以资鼓励: