Linux lsof命令使用详解
lsof(listopenfiles)是一个查看进程打开的文件的工具。
在linux系统中,一切皆文件。通过文件不仅仅可以访问常规数据,还可以访问网络连接和硬件。所以lsof命令不仅可以查看进程打开的文件、目录,还可以查看进程监听的端口等socket相关的信息。本文将介绍lsof命令的基本用法,本文中demo的演示环境为ubuntu18.04。
常用选项
-a指示其它选项之间为与的关系
-c<进程名>输出指定进程所打开的文件
-d<文件描述符>列出占用该文件号的进程
+d<目录>输出目录及目录下被打开的文件和目录(不递归)
+D<目录>递归输出及目录下被打开的文件和目录
-i<条件>输出符合条件与网络相关的文件
-n不解析主机名
-p<进程号>输出指定PID的进程所打开的文件
-P不解析端口号
-t只输出PID
-u输出指定用户打开的文件
-U输出打开的UNIXdomainsocket文件
-h显示帮助信息
-v显示版本信息
基本输出
如果不带任何选项执行lsof命令,会输出系统中所有active进程打开的所有文件,结果就是我们被输出的信息所淹没,这没有任何的意义。我们先让lsof命令输出当前Bash进程打开的文件,并截取其中的一部分结果来介绍输出内容中都包含哪些信息:
COMMAND:程序的名称
PID:进程标识符
USER:进程所有者
FD:文件描述符,应用程序通过文件描述符识别该文件
TYPE:文件类型,如DIR、REG等
DEVICE:以逗号分隔设备编号
SIZE:文件的大小(bytes)
NODE:索引节点(文件在磁盘上的标识)
NAME:打开文件的确切名称
下面简单介绍一下FD列和TYPE列中的常见内容。
FD列中的常见内容有cwd、rtd、txt、mem和一些数字等等。其中cwd表示当前的工作目录;rtd表示根目录;txt表示程序的可执行文件;mem表示内存映射文件:
还有一部分FD是以数字表示的,比如标准输入输出文件:
数字后面的字母表示进程对该文件的读写模式,比如上图中的u表示该文件被打开并处于读取/写入模式。除了u,还有r表示只读模式,w表示只写模式,还可以同时应用W表示该进程拥有对文件写操作的锁。下图是截取的dockerdaemon进程打开的文件列表,其中显示了FD的不同模式:
TYPE列中常见的REG和DIR分别表示普通文件和目录。而CHR和BLK则分别表示字符和块设备,unix、fifo和IPv4/IPv6分别表示UNIXdomain套接字、先进先出(FIFO)队列和IPv4/IPv6套接字。
下面我们来介绍一些lsof命令的常见用法。
查看哪些进程打开了某个文件
直接指定文件的名称作为lsof的参加就可以查看哪些进程打开了这个文件,下面的命令查询打开了/bin/bash文件的进程:
$sudolsof/bin/bash
除了普通文件,也可以是设备等文件(下面命令的输出很长,图示只是截取的一小部分):
$sudolsof/dev/sda1
查看哪些进程打开了某个目录及目录下的文件
这里分两种情况,+d选项不执行递归查询,只查找那些打开了指定目录以及指定目录下文件和目录的进程,比如:
$sudolsof+d/var/log
而+D选项则会对指定的目录进行递归:
$sudolsof+D/var/log
在卸载文件系统时,如果有进程打开了该文件系统中的文件或目录,卸载操作就会失败。因此最好在卸载文件系统前通过lsof+D检查文件系统的挂载点,杀掉相关的进程然后再执行卸载操作。
查看某个进程打开的所有文件
通过-p选项并指定进程的PID可以输出该进程打开的所有文件。比如我们想要查看cron程序打开的文件,可以先用ps-Ccron命令查出进程的PID:
然后把该PID传递给lsof命令的-p选项:
$sudolsof-p1152
组合多个选项
如果为lsof命令指定多个选项,这些选项间默认是或的关系。也就是说满足任何一个选项的结果都会被输出。可以添加额外的-a选项,它的作用就是让其它选项之间的关系变为与,比如下面的命令:
$sudolsof-a-p$$-d0,1,2
其中的-p选项指定了当前进程的PID,而-d选项则用来指定进程打开的文件描述符(可以通过逗号分隔多个文件描述符)。添加-a选项后,结果输出为当前进程打开的文件描述符为0、1、2的文件。
说明,-a选项的使用有很多条件,具体请参考lsofmanpage。
查看指定名称的程序打开的文件
通过-c选项可以匹配进程运行的程序(可执行文件)名称。比如我们要查找以字母cr开头的程序打开的文件列表:
$sudolsof-ccr
还可以同时指定多个-c选项,它们之间是或的关系。
如果想对-c选项的条件取反,只要在字符串前添加符号^就可以了,比如:
$sudolsof-c^cr
-c选项也支持正则表达式,比如下面的命令可以过滤出以cra和cro开头的程序打开的文件:
$sudolsof-c/cr[ao]/
查看被打开的与网络相关的文件
-i选项用来查看被打开的和网络相关的文件,其参数的格式如下:
[46][protocol][@hostname|hostaddr][:service|port]
46表示IP协议的版本
protocol表示网络协议的名称,比如TCP或UDP
hostname或hostaddr表示主机地址
service指/etc/services中的名称,比如smtp或多个服务的列表
port表示端口号,可以指定一个或多个
-i选项默认会同时输出IPv4和IPv6打开的文件:
$sudolsof-i
只列出IPv4或IPv6打开的文件
$sudolsof-i4 $sudolsof-i6
列出与22号端口相关的文件
$sudolsof-i:22
列出指定范围内被打开的TCP端口
$sudo-iTCP:1-1024
查看被打开的UNIXdomainsocket文件
-U选项输出打开的UNIXdomainsocket文件,这里我们结合-c选项来查看ssh服务打开的UNIXdomainsocket文件:
$sudolsof-a-csshd-U
查看某个用户打开的所有文件
-u选项可以指定用户名或userID,并且和-c选项一样,可以通过逗号分隔多个用户名称或userID,也可以通过符号^对条件取反。
查看某个用户打开的所有文件
$sudolsof-usyslog
查看用户nick打开的网络相关的文件
$sudolsof-a-i-unick
排除某个用户
$sudolsof-i-u^nick
注意:在有排除条件时,不需要指定-a选项。
杀掉某个用户打开了文件的所有进程
$kill-9$(lsof-t-unick)
该命令中的-t选项让lsof命令只输出进程的PID:
统计系统打开的文件总数
$sudolsof-P-n|wc-l
命令中的-P选项表示不解析端口号,-n选项表示不解析主机名,这两个选项主要的目的是为了提升lsof命令的执行速度。wc-l命令则用来统计lsof命令输出的行数。
恢复删除的文件
如果我们一不小心删除了文件,而又知道这个文本被某个进程打开着,就可以通过lsof命令来恢复该文件。具体的原理为:
当进程打开了某个文件时,只要该进程保持打开该文件,即使将文件删除,它依然存在于磁盘中。进程并不知道文件已经被删除,它仍然可以通过打开该文件时提供给它的文件描述符进行读取和写入。除了该进程之外,这个文件是不可见的,因为已经删除了其相应的目录索引节点。
进程打开的文件描述符就存放在/proc/PID/fd目录下。/proc目录挂载的是在内存中所映射的一块区域,所以这些文件和目录并不存在于磁盘中,因此当我们对这些文件进行读取和写入时,实际上是在从内存中获取相关信息。lsof程序就是使用这些信息和其他关于内核内部状态的信息来产生其输出。所以lsof可以显示进程的文件描述符和相关的文件名等信息。也就是说我们通过访问进程的文件描述符可以找到该文件的相关信息。
下面的demo演示如何通过lsof命令恢复被误删的/var/log/syslog文件。
先删除日志文件/var/log/syslog,记着要提前备份一下这个文件,以防万一:
$sudorm/var/log/syslog
从上面的信息可以看到PID为1141的进程打开着该文件,文件描述符为7,并且显示该文件已经被删除了。接下来我们通过1141号进程的文件文件描述符来查看该文件的内容:
$sudotail-n5/proc/1141/fd/7
上图说明文件/var/log/syslog文件的内容还在,并且可以通过文件描述符访问,接下来通过IO重定向的方式重新创建/var/log/syslog文件就可以了:
$sudosh-c'cat/proc/1141/fd/7>/var/log/syslog'
然后修复文件的权限属性并重启rsyslog服务:
$sudochownsyslog:adm/var/log/syslog $sudosystemctlrestartrsyslog.service
这样就完成了/var/log/syslog文件的恢复工作。对于许多应用程序,尤其是日志文件和数据库文件,都可以通过这种方式来恢复。
帮助
-h选项会输出lsof命令的帮助信息:
估计这样的帮助信息也只能逼着你去读manpage了!
总结
lsof并不是一个简单的命令,从其manpage的长度就可以体会到这一点。从本文介绍的小demo入手或许可以让你忘记冗长的文档说明,一步步的开始使用并最终掌握这个命令。
参考:
lsofmanpage
linuxlsof命令详解
10lsofCommandExamplesinLinux
LinuxlsofCommandTutorialforBeginners(10Examples)
15LinuxlsofCommandExamples(IdentifyOpenFiles)
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持毛票票。
声明:本文内容来源于网络,版权归原作者所有,内容由互联网用户自发贡献自行上传,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任。如果您发现有涉嫌版权的内容,欢迎发送邮件至:czq8825#qq.com(发邮件时,请将#更换为@)进行举报,并提供相关证据,一经查实,本站将立刻删除涉嫌侵权内容。