lsof

一、简介

 lsof(list open files)是一个列出当前系统打开文件的工具。在linux环境下,任何事物都以文件的形式存在,通过文件不仅仅可以访问常规数据,还可以访问网络连接和硬件。

 所以如传输控制协议 (TCP) 和用户数据报协议 (UDP) 套接字等,系统在后台都为该应用程序分配了一个文件描述符,无论这个文件的本质如何,该文件描述符为应用程序与基础操作系统之间的交互提供了通用接口。

 

二、详解

 2.1、输出信息每列字段含义(root权限)

COMMAND    进程名
PID        进程标识符
USER       进程所有者
FD         文件描述符,应用程序通过文件描述符识别该文件。如cwd、txt等,后文详细列出
TYPE       文件类型,如DIR、REG等
DEVICE     指定磁盘的名称
SIZE       文件的大小(单位:字节Byte)
NODE       索引节点(文件在磁盘上的标识)
NAME       打开文件的确切名称

 

 2.2、参数

  语法:lsof [options] filename

lsof filename     显示打开指定文件的所有进程
lsof -a         表示两个参数都必须满足时才显示结果
lsof -c string     显示COMMAND列中包含指定字符的进程所有打开的文件
lsof -u username    显示所属user进程打开的文件
lsof -g gid      显示归属gid的进程情况
lsof +d /DIR/     显示目录下被进程打开的文件
lsof +D /DIR/     同上,但是会搜索目录下的所有目录,时间相对较长
lsof -d FD       显示指定文件描述符的进程
lsof -n        不将IP转换为hostname,缺省是不加上-n参数
lsof -i        用以显示符合条件的进程情况
lsof -i[46] [protocol][@hostname|hostaddr][:service|port]
                 46 --> IPv4 or IPv6
                 protocol --> TCP or UDP
                 hostname --> Internet host name
                 hostaddr --> IPv4地址
                 service --> /etc/service中的 service name (可以不只一个)
                 port --> 端口号 (可以不只一个)

 

 2.3、示例

lsof | grep deleted  查看文件没释放的
lsof `which httpd`   哪个进程在使用nginx的可执行文件(which+进程名 可查看进程的执行文件) lsof
/etc/passwd    哪个进程在占用/etc/passwd lsof /dev/hda6      哪个进程在占用hda6(/dev/xxx hd-硬盘类型 a-第一块盘 6-第2个逻辑分区,逻辑分区从5开始) lsof /dev/cdrom     哪个进程在占用光驱
lsof
-c mysql     -c 选项将会列出所有以mysql开头的程序的文件(-c mysql -c nginx 可查看多个进程打开的文件) lsof -c courier -u ^zahn     显示出那些文件被以courier打头的进程打开,但是并不属于用户zahn lsof -p 30297      显示那些文件被pid为30297的进程打开
lsof -p 进程号 -nP | grep TCP  查看进程连接情况(-nP参数用于将ip地址和端口号显示为正常的数值类型,否则可能会用别名表示) lsof
-D /tmp/test    递归查看某个目录的文件信息

lsof -U         显示所有socket文件
lsof -a -u root -i   列出root用户所有活跃的网络端口 lsof
-u1000       查看uid是100的用户的进程的文件使用情况 lsof -utony       查看用户tony的进程的文件使用情况 lsof -u^tony       查看不是用户tony的进程的文件使用情况(^是取反的意思)
     lsof
-i          显示所有打开的端口 lsof -i:80        显示所有打开80端口的进程 lsof -i -U        显示所有打开的端口和UNIX domain文件

lsof -i tcp       列出所有tcp网络连接信息
lsof -i udp       列出所有udp网络连接信息 lsof
-i UDP@[url]www.baidu.com:123        显示那些进程打开了到www.baidu.com的UDP的123(ntp)端口的链接 lsof -i tcp@ohaha.ks.edu.tw:ftp -r         不断查看目前ftp连接的情况(-r,lsof会永远不断的执行,直到收到中断信号,+r,lsof会一直执行,直到没有档案被显示,缺省是15s刷新) lsof -i tcp@ohaha.ks.edu.tw:ftp -n lsof -n    不将IP转换为hostname,缺省是不加上-n参数

 

 2.4、使用lsof恢复删除的进程使用的文件(必须是有进程在使用这个文件,且是被delete但是仍然是open的文件

  原理:在Linux系统的/proc 分区下保存着进程的目录和名字,包含fd(文件描述符)和其下的子目录(进程打开文件的链接),那么如果删除了一个文件,还存在一个 inode的引用

      当不小心用了 rm -f  删除文件时,其实只是删除了文件的目录索引节点,对于文件系统不可见,但是对于打开它的进程依然可见,就可以使用I/O重定向的方式来恢复文件。

  示例:以/var/log/messages 为例

#测试前先cp,养成好习惯
cp /var/log/messages /var/log/messages.bak
#删除文件 rm
-f /var/log/messages
#查看这个文件信息(/proc/进程号/fd/文件描述符) lsof
| grep /var/log/messages
#查看/proc对应留存的信息,比对拷贝的信息 cat
/proc/225/fd/4
cat /var/log/messages
#重定向恢复文件
cat
/proc/225/fd/4 > /var/log/messages

 

 

 

 2.5、每字段含义详解

  1)文件描述符

    内核(kernel)利用文件描述符(file descriptor)来访问文件。文件描述符是非负整数。打开现存文件或新建文件时,内核会返回一个文件描述符。读写文件也需要使用文件描述符来指定待读写的文件。

   常见内容有 cwd、rtd、txt、mem 和一些数字等等。其中 cwd 表示当前的工作目录;rtd 表示根目录;txt 表示程序的可执行文件;mem 表示内存映射文件

   还有一部分 FD 是以数字表示的,如标准输入输出文件,数字后面的字母表示进程对该文件的读写模式,比如上图中的 u 表示该文件被打开并处于读取/写入模式。除了 u,还有 r 表示只读模式,w 表示只写模式,还可以同时应用 W 表示该进程拥有对文件写操作的锁

  2)文件类型

DIR:表示目录
CHR:表示字符类型
BLK:块设备类型
UNIX: UNIX 域套接字 FIFO:先进先出 (FIFO) 队列 IPv4:网际协议 (IP) 套接字

  3)文件大小单位换算

1 Byte = 8 Bits(即 1B=8b)
1 KB = 1024 Bytes
1 MB = 1024 KB
1 GB = 1024 MB
1 TB = 1024 GB

 

三、补充

3.1 文件描述符&文件句柄

#查看当前使用的文件句柄数
#三列数据分别为:已分配文件句柄的数目,已分配未使用文件句柄的数目,文件句柄的最大数目
cat /proc/sys/fs/file-nr

#查看当前已使用的文件描述符数
lsof -P -n| wc -l

两条命令有较大差距,原因是:

file-nr文件里面的第一个字段代表的是内核分配的struct file的个数,也就是文件句柄个数,而不是文件描述符

lsof的结果包含了并非以fd形式打开的文件,比如用mmap方式访问文件(fd一栏显示为mem),实际并不占用fd。其中包括了像.so和.jar文件,也是以fd为mem和具体fd编号分别打开了一次

lsof是通过查看进程的内存映射和文件描述符表来枚举打开文件的, 如果是一个多线程的服务。主线程先退出了,子线程还活着, 那么进程的fd表看起来就是空的

lsof看到的是文件描述符不能代表文件句柄

 

查看哪个进程的文件描述符最多:

#fd数量
find /proc -print | grep -P '/proc/\d+/fd/'| awk -F '/' '{print $3}' | uniq -c | sort -rn | head
lsof | awk '{print $2}' | uniq -c | sort -rnk1
#具体进程的fd数
ls -l /proc/<pid>/fd | wc -l

 

3.2 lsof: no pwd entry for UID 70

今天在清理磁盘的时候,执行 lsof | grep deleted 时,出现很多 lsof: no pwd entry for UID 70 的报错,网上查原因有两个:

1、进程在用户被删除之前启动,并且从那以后一直在运行

2、进程在容器内被启动(该UID为容器内的用户ID)

可以使用-w参数忽略这些错误 lsof -w | grep deleted 

 

posted @ 2021-10-12 09:43  心恩惠动  阅读(422)  评论(0编辑  收藏  举报