5.5 lsof
lsof 命令是 Linux 系统的扩展工具,它的含义是 list opened filedesciptor (列出已经打开的文件描述符),在 Linux 系统中,所有的与资源句柄相关的东西都可以统一抽象成文件描述符(filedescriptor,简称 fd)。一个文件句柄是一个 fd,一个 socket 对象也可以称之为 fd 等等。
# 5.5.1 lsof 命令的基本用法
默认情况下,系统是不存在这个命令的,你需要安装一下,使用如下命令安装:
yum install lsof
我们来看一下这个命令的使用效果:
COMMAND PID TID USER FD TYPE DEVICE SIZE/OFF NODE NAME
systemd 1 root cwd DIR 202,1 4096 2 /
nscd 453 469 nscd 8u netlink 0t0 11017 ROUTE
nscd 453 470 nscd cwd DIR 202,1 4096 2 /
nscd 453 470 nscd rtd DIR 202,1 4096 2 /
nscd 453 470 nscd txt REG 202,1 180272 146455 /usr/sbin/nscd
nscd 453 470 nscd mem REG 202,1 217032 401548 /var/db/nscd/hosts
nscd 453 470 nscd mem REG 202,1 90664 132818 /usr/lib64/libz.so.1.2.7
nscd 453 470 nscd mem REG 202,1 68192 133155 /usr/lib64/libbz2.so.1.0.6
nscd 453 470 nscd mem REG 202,1 153192 133002 /usr/lib64/liblzma.so.5.0.99
nscd 453 470 nscd mem REG 202,1 91496 133088
nscd 453 471 nscd 5u a_inode 0,9 0 4796 [eventpoll]
nscd 453 471 nscd 6r REG 202,1 217032 401548 /var/db/nscd/hosts
nscd 453 471 nscd 7u unix 0xffff880037497440 0t0 11015 /var/run/nscd/socket
nscd 453 471 nscd 8u netlink 0t0 11017 ROUTE
imgserver 611 zhangyl cwd DIR 202,1 4096 1059054 /home/zhangyl/flamingoserver
imgserver 611 zhangyl rtd DIR 202,1 4096 2 /
imgserver 611 zhangyl txt REG 202,1 4788917 1057044 /home/zhangyl/flamingoserver/imgserver
imgserver 611 zhangyl 24u a_inode 0,9 0 4796 [eventfd]
imgserver 611 zhangyl 25u IPv4 55707643 0t0 TCP *:commtact-http (LISTEN)
imgserver 611 zhangyl 26r CHR 1,3 0t0 4800 /dev/null
imgserver 611 613 zhangyl 32w REG 202,1 131072 2754609 /home/zhangyl/flamingoserver/imgcache/258bfb8945288a117d98d440986d7a03
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
结果显示中列出了各个进程打开的各种 fd 类型,对于 Uinx Socket,lsof 命令会显示出其详细的路径,打开的文件 fd 亦是如此。
使用 lsof 命令有三点需要注意:
默认情况下,lsof 的输出比较多,我们可以使用 grep 命令过滤我们想要查看的进程打开的 fd 信息,如:
lsof -i | grep myapp
1或者使用 lsof -p pid 也能过滤出指定的进程打开的 fd 信息:
[root@iZ238vnojlyZ ~]# lsof -p 26621 COMMAND PID USER FD TYPE DEVICE SIZE/OFF NODE NAME chatserve 26621 zhangyl cwd DIR 202,1 4096 1059054 /home/zhangyl/flamingoserver chatserve 26621 zhangyl rtd DIR 202,1 4096 2 / chatserve 26621 zhangyl txt REG 202,1 8027035 1051942 /home/zhangyl/flamingoserver/chatserver chatserve 26621 zhangyl mem REG 202,1 61928 141417 /usr/lib64/libnss_files-2.17.so chatserve 26621 zhangyl mem REG 202,1 44096 143235 /usr/lib64/librt-2.17.so chatserve 26621 zhangyl mem REG 202,1 19520 137064 /usr/lib64/libdl-2.17.so chatserve 26621 zhangyl mem REG 202,1 2112384 132824 /usr/lib64/libc-2.17.so chatserve 26621 zhangyl mem REG 202,1 142304 132850 /usr/lib64/libpthread-2.17.so chatserve 26621 zhangyl mem REG 202,1 88720 135291 /usr/lib64/libgcc_s-4.8.5-20150702.so.1 chatserve 26621 zhangyl mem REG 202,1 1141560 137077 /usr/lib64/libm-2.17.so chatserve 26621 zhangyl mem REG 202,1 999944 140059 /usr/lib64/libstdc++.so.6.0.19 chatserve 26621 zhangyl mem REG 202,1 9879756 269001 /usr/lib64/mysql/libmysqlclient.so.20.3.4 chatserve 26621 zhangyl mem REG 202,1 164440 133622 /usr/lib64/ld-2.17.so chatserve 26621 zhangyl 0u CHR 1,3 0t0 4800 /dev/null chatserve 26621 zhangyl 1u CHR 1,3 0t0 4800 /dev/null chatserve 26621 zhangyl 2u CHR 1,3 0t0 4800 /dev/null chatserve 26621 zhangyl 3u a_inode 0,9 0 4796 [eventpoll] chatserve 26621 zhangyl 4u a_inode 0,9 0 4796 [timerfd] chatserve 26621 zhangyl 5u a_inode 0,9 0 4796 [eventfd] chatserve 26621 zhangyl 7u a_inode 0,9 0 4796 [eventpoll]
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22lsof 命令只能查看到当前用户有权限查看到的进程 fd 信息,对于其没有权限的进程,最右边一列会显示 “Permission denied”。如下所示:
sshd 26759 root cwd unknown /proc/26759/cwd (readlink: Permission denied) sshd 26759 root rtd unknown /proc/26759/root (readlink: Permission denied) sshd 26759 root txt unknown /proc/26759/exe (readlink: Permission denied) sshd 26759 root NOFD /proc/26759/fd (opendir: Permission denied) bash 26761 root cwd unknown /proc/26761/cwd (readlink: Permission denied) bash 26761 root rtd unknown /proc/26761/root (readlink: Permission denied) bash 26761 root txt unknown /proc/26761/exe (readlink: Permission denied) bash 26761 root NOFD /proc/26761/fd (opendir: Permission denied)
1
2
3
4
5
6
7
8lsof 命令第一栏进程名在显示的时候,默认显示前 n 个字符,这样如果我们需要显示完整的进程名以方便过滤的话,可以使用 +c 选项。用法如下:
#最左侧的程序名最大显示 15 个字符 [zhangyl@iZ238vnojlyZ ~]$ lsof +c 15
1
2当然,如果你设置值太大, lsof 便不会采用你设置的最大值,而是使用默认最大值。
上文也介绍了,socket 也是一种 fd,如果需要仅显示系统的网络连接信息,使用的是 -i 选项即可,这个选项可以形象地显示出系统当前的出入连接情况:
看到图中的连接方向了吧?
当然,和 netstat 命令一样,lsof -i 默认也会显示 ip 地址和端口号的别名,我们只要使用 -n 和 -P 选项就能相对应地显示 ip 地址和端口号了,综合起来就是 lsof -Pni:
# 5.5.2 使用 lsof 命令恢复被删除的文件
这里再介绍一个利用 lsof 命令恢复被删除的文件的小技巧。下面我们来演示一下,为了避免出现意外造成损失,建议读者在实验之前备份要删除的文件。
某时某刻,某个日志文件 fileserver.20190814145718.12975.log 被一个叫 fileserver 的程序正使用着。我们可以使用 lsof 命令验证:
[zhangyl@iZ238vnojlyZ logs]$ lsof | grep fileserve
上图的输出证明 fileserver.20190814145718.12975.log 确实被进程 fileserver 使用,进程 ID 是 12976。
我们将该日志文件删除:
[zhangyl@iZ238vnojlyZ logs]$ rm -rf fileserver.20190814145718.12975.log
然后再次使用 lsof 查看一下进程 fileserver 使用该文件的状态信息:
此时该进程中该文件已经被标记为 deleted 状态了。
我们进入目录 /proc/pid/fd/
并使用 ll (ls -l 的别名)命令查看文件状态,这里的 pid 要换成相应进程的 ID,这里就是 12976:
[zhangyl@iZ238vnojlyZ 12976]$ cd /proc/12976/fd/
[zhangyl@iZ238vnojlyZ fd]$ ll
2
此时我们到了被删除的文件:
标号 6 正好对应我们删除的文件,使用这个标号进行恢复:
[zhangyl@iZ238vnojlyZ fd]$ cat 6 > /home/zhangyl/flamingoserver/logs/fileserver.20190814145718.12975.log
这样我们的文件就被恢复到 /home/zhangyl/flamingoserver/logs/
目录处了。
使用 lsof 命令恢复的文件需要注意两点:
如果想成功恢复文件,使用文件的进程必须处于存活状态,这里如果 fileserver 已经退出或被杀死,那就无法用这种方式恢复。
用这种方式恢复的文件,再次用 lsof 命令查看时这个文件的状态仍然是 deleted 状态,也就是说虽然能够手工恢复,但是进程不会再使用这个文件了。对于这里的日志文件,fileserver 继续运行也不会再往这个文件中写入日志了。所以这里恢复文件一般只是用于某些特殊情况下删除一些重要数据文件的应急恢复。