赞
踩
在linux系统中,一切皆文件。通过文件不仅仅可以访问常规数据,还可以访问网络连接和硬件。 所以lsof
命令不仅可以查看进程打开的文件、目录,还可以查看进程监听的端口等socket相关的信息。
https://man7.org/linux/man-pages/man8/lsof.8.html
-a 指示其它选项之间为与的关系
-c <进程名> 输出指定进程所打开的文件
-d <文件描述符> 列出占用该文件号的进程
+d<目录> 输出目录及目录下被打开的文件和目录(不递归)
+D <目录> 递归输出及目录下被打开的文件和目录
-i <条件> 输出符合条件与网络相关的文件
-n 不解析主机名
-p <进程号> 输出指定 PID 的进程所打开的文件
-P 不解析端口号
-t 只输出 PID
-u 输出指定用户打开的文件
-U 输出打开的 UNIX domain socket 文件
-h 显示帮助信息
-v 显示版本信息
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 表示该进程拥有对文件写操作的锁。
TYPE 列中常见的 REG 和 DIR 分别表示普通文件和目录。
而 CHR 和 BLK 则分别表示字符和块设备,unix、fifo 和 IPv4/IPv6 分别表示 UNIX domain套接字、先进先出(FIFO)队列和IPv4/IPv6 套接字。
# lsof /usr/lib64/libfipscheck.so.1.2.1
# lsof /dev/vda1
这里分两种情况,+d 选项不执行递归查询,只查找那些打开了指定目录以及指定目录下文件和目录的进程,而 +D 选项则会对指定的目录进行递归。
# lsof +D /var/log
lsof +d /var/log
在卸载文件系统时,如果有进程打开了该文件系统中的文件或目录,卸载操作就会失败。
因此最好在卸载文件系统前通过 lsof +D 检查文件系统的挂载点,杀掉相关的进程然后再执行卸载操作。
通过 -p 选项并指定进程的 PID 可以输出该进程打开的所有文件。
然后把该 PID 传递给 lsof 命令的 -p 选项:
lsof -p 1335
lsof -c sshd
还可以同时指定多个 -c 选项,它们之间是或的关系。
如果想对 -c 选项的条件取反,只要在字符串前添加符号 ^ 就可以。
-c 选项也支持正则表达式,比如下面的命令可以过滤出以 cra 和 cro 开头的程序打开的文件。
-i 选项用来查看被打开的和网络相关的文件,其参数的格式如下:
[46][protocol][@hostname|hostaddr][:service|port]
46 表示 IP 协议的版本
protocol 表示网络协议的名称,比如 TCP 或 UDP
hostname 或 hostaddr 表示主机地址
service 指 /etc/services 中的名称,比如 smtp 或多个服务的列表
port 表示端口号,可以指定一个或多个
-i 选项默认会同时输出 IPv4 和 IPv6 打开的文件:
# lsof -i
列出与 323 号端口相关的文件
# lsof -i:323
只列出 IPv4 或 IPv6 打开的文件
lsof -i 4
lsof -i 6
列出指定范围内被打开的 TCP 端口
lsof -i TCP:1-1024
-u 选项可以指定用户名或 user ID,并且和 -c 选项一样,可以通过逗号分隔多个用户名称或 user ID,也可以通过符号 ^ 对条件取反。
查看某个用户打开的所有文件
# lsof -u root
杀掉某个用户打开了文件的所有进程
kill -9 $(lsof -t -u nick)
该命令中的 -t 选项让 lsof 命令只输出进程的PID统计系统打开的文件总数
lsof -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,记着要提前备份一下这个文件,以防万一:
#rm /var/log/syslog
从上面的信息可以看到 PID 为 693的进程打开着该文件,文件描述符为 8,并且显示该文件已经被删除了。接下来我们通过 1141 号进程的文件文件描述符来查看该文件的内容:
上图说明文件 /var/log/maillog 文件的内容还在,并且可以通过文件描述符访问,接下来通过 IO 重定向的方式重新创建 /var/log/maillog 文件就可以了:
# sh -c 'cat /proc/693/fd/8 > /var/log/maillog'
然后修复文件的权限属性并重启 rsyslog 服务:
systemctl restart rsyslog.service
这样就完成 /var/log/maillog 文件的恢复工作。对于许多应用程序,尤其是日志文件和数据库文件,都可以通过这种方式来恢复。
lsof -i: tcpdump -c 1 -i eth0 host 192.168.0.16 -l | awk '{print $5}' | awk -F '.' '{print $5}' |awk -F ':' '{print $1}'
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。