用lsof列出当前正在被打开的文件
一,lsof有什么用?
lsof可以找出被特定进程所打开的文件,目录,套接字,设备.
例子:比如有时我们不能umount掉一个分区时,我们会需要检查,是哪些进程在使用当前的分区
以便找出进程后将它关闭
一个与脚本相关的例子:
我们使用ftp接收别人上传的文件,有程序被放到crond中定时进行处理,
此时就有一个问题;我们如何得知当前被处理的文件是否上传完了,
比如:如果上传的是一张图片,且正在传输中我们就进行了处理,则我们会得到一张残缺不全的图片
解决方法:用lsof对文件进行检查,如果有进程在访问,就表示还未上传完成,可以先跳过当前文件
二,lsof的用法举例
1,检查目录和文件
[root@localhost cdrom]# umount /mnt/cdrom
umount: /mnt/cdrom: device is busy.
(In some cases useful info about processes that use
the device is found by lsof(8) or fuser(1))
在做umount设备时, device is busy是令人头痛的提示
大家看,我使用的是fedora 10,umount会自动给出让大家用lsof或fuser进行检测的信息
[root@localhost cdrom]# lsof /mnt/cdrom
COMMAND PID USER FD TYPE DEVICE SIZE/OFF NODE NAME
bash 2705 root cwd DIR 8,1 8192 1 /mnt/cdrom
lsof 2756 root cwd DIR 8,1 8192 1 /mnt/cdrom
lsof 2757 root cwd DIR 8,1 8192 1 /mnt/cdrom
可以看到,有3个进程在访问/mnt/cdrom,程序分别是 bash和lsof,
lsof给出的信息很全,还列出了进程的id及用户
因为我们当前就处在cdrom目录下,所以bash也是其中打开cdrom目录的一个进程
下面我们从目录下退出:
[root@localhost winc]# cd
[root@localhost ~]# umount /mnt/cdrom
这个例子提醒大家:如果umount一个分区时,lsof列出的进程中有bash,
通常是有用户登录在此目录下,通知用户让他从目录下cd出来就可以了
还有一种情况:如果是apache在访问当前分区怎么办?
象apache或其他daemon在访问分区,很简单,
只需要停止daemon就可以了
2,有没有这种可能:我们用lsof看不到进程,但是在做umount时系统仍然提示 device is busy?
有这种可能,
一个例子:
[root@search root]# umount /store2
umount: /store2: device is busy
[root@search root]# lsof /store2
很奇怪,我们用lsof看不到访问/store2的进程,但umount时系统却告诉我们说:
device is busy
为什么会这样?
是因为有可能nfs正在使用此进程
查看/etc/exports,此目录便位于其中
[root@search root]# cat /etc/exports
/store2 201.103.105.37(rw,sync,no_root_squash)
/store2 201.103.105.36(rw,sync,no_root_squash)
此时如何处理?
把/etc/exports中的nfs出去的目录注释掉,用#加在每一行前面即可
然后无需重启 nfs,执行 exportfs -rv即可
3,根据进程id得到其打开的文件列表:
我们查看一个apache进程所打开的文件列表:
[root@www ~]# lsof -p 2759
COMMAND PID USER FD TYPE DEVICE SIZE NODE NAME
httpd 2759 nobody cwd DIR 253,0 4096 2 /
httpd 2759 nobody rtd DIR 253,0 4096 2 /
httpd 2759 nobody txt REG 253,0 1885982 4622117 /usr/local/apache2/bin/httpd
httpd 2759 nobody mem REG 253,0 334391 4621269 /usr/local/apache2/lib/libaprutil-0.so.0.9.12
httpd 2759 nobody mem REG 253,0 374273 4621265 /usr/local/apache2/lib/libexpat.so.0.1.0
httpd 2759 nobody mem REG 253,0 578133 4621251 /usr/local/apache2/lib/libapr-0.so.0.9.12
httpd 2759 nobody mem REG 253,0 21546 4407507 /usr/lib64/gconv/gconv-modules.cache
httpd 2759 nobody mem REG 253,0 30070 9519340 /lib64/libcrypt-2.3.4.so
httpd 2759 nobody mem REG 253,0 18848742 4622118 /usr/local/apache2/modules/libphp5.so
......
它打开的文件很多,我不再全列出
4,列出某个终端上的用户正在做什么?
例如:
我们先登录到一个终端上面:(先用tty得到当前终端)
[root@search root]# tty
/dev/pts/2
[root@search root]# cat
然后登录到另一终端:
[root@search root]# lsof /dev/pts/2
COMMAND PID USER FD TYPE DEVICE SIZE NODE NAME
cat 514 root 0u CHR 136,2 4 /dev/pts/2
cat 514 root 1u CHR 136,2 4 /dev/pts/2
cat 514 root 2u CHR 136,2 4 /dev/pts/2
bash 32551 root 0u CHR 136,2 4 /dev/pts/2
bash 32551 root 1u CHR 136,2 4 /dev/pts/2
bash 32551 root 2u CHR 136,2 4 /dev/pts/2
bash 32551 root 255u CHR 136,2 4 /dev/pts/2
5,列出所有命令名字相同的进程所打开的全部文件
例如:apache的进程名命令全部都是httpd
我们列出apache打开的所有进程时,可以使用 -c参数,
[root@search yc]# lsof -c httpd
COMMAND PID USER FD TYPE DEVICE SIZE NODE NAME
httpd 15722 root cwd DIR 8,8 4096 2 /
httpd 15722 root rtd DIR 8,8 4096 2 /
httpd 15722 root txt REG 8,2 1701872 1087581 /usr/local/apache/bin/httpd
httpd 15722 root mem REG 8,8 103044 31946 /lib/ld-2.3.2.so
httpd 15722 root mem REG 8,8 23668 31955 /lib/libcrypt-2.3.2.so
httpd 15722 root mem REG 8,2 877128 69041 /usr/lib/libsablot.so.0.100.1
httpd 15722 root mem REG 8,2 442752 69039 /usr/lib/libjs.so
httpd 15722 root mem REG 8,2 130104 64938 /usr/lib/libexpat.so.0.4.0
httpd 15722 root mem REG 8,2 52616 64985 /usr/lib/libz.so.1.1.4
httpd 15722 root mem REG 8,2 136068 66295 /usr/lib/libcurl.so.2.0.2
httpd 15722 root mem REG 8,8 76552 31977 /lib/libresolv-2.3.2.so
httpd 15722 root mem REG 8,8 211948 95819 /lib/tls/libm-2.3.2.so
......
进程太多,不一一列举
6,根据目录,列出指定目录下被进程打开的文件或目录
先看两个参数:
+d,只搜索当前目录下被打开的文件或目录
+D,递归搜索当前目录下被打开的文件或目录
(注意此参数会导至速度变慢)
例子:
[root@search yc]# mkdir abc
[root@search yc]# cd abc/
在另一终端执行lsof
[root@search root]# lsof +d /store2/yc/
COMMAND PID USER FD TYPE DEVICE SIZE NODE NAME
bash 32473 root cwd DIR 8,16 4096 111329281 /store2/yc/abc
下面我们再深入一层目录
[root@search abc]# mkdir def
[root@search abc]# cd def
还是到另一终端执行lsof
[root@search root]# lsof +d /store2/yc/
[root@search root]#
看不到进程了,因为def不再是直接在/store2/yc目录下,而是更下一层,则此时需要+D
[root@search root]# lsof +D /store2/yc/
COMMAND PID USER FD TYPE DEVICE SIZE NODE NAME
bash 32473 root cwd DIR 8,16 4096 111345665 /store2/yc/abc/def
7,查看打开某个端口的所有进程
[root@search root]# lsof -i :80
COMMAND PID USER FD TYPE DEVICE SIZE NODE NAME
httpd 15722 root 22u IPv4 1863715557 TCP *:http (LISTEN)
httpd 28161 nobody 22u IPv4 1863715557 TCP *:http (LISTEN)
httpd 28162 nobody 22u IPv4 1863715557 TCP *:http (LISTEN)
httpd 28163 nobody 22u IPv4 1863715557 TCP *:http (LISTEN)
.......
[root@search root]# lsof -i :21
COMMAND PID USER FD TYPE DEVICE SIZE NODE NAME
xinetd 9362 root 6u IPv4 -1253197382 TCP *:ftp (LISTEN)
原文地址:http://blog.chinaunix.net/u2/82938/showart_1832073.html