linux命令之lsof

这是“您应该知道的UNIX工具系列主题文章”的第三篇。在这篇文章里,我将介绍一个很有用的工具—lsof。如果说netcat是网络连接的瑞士军刀,那么我说lsofUNIX调试的瑞士军刀。

Lsof严格遵循UNIX的哲学典范。它仅完成一项任务,并且做得极尽完美----它能够列出某个进程所打开的文件信息。打开的文件可以是普通文件、目录、NFS文件、块文件、字符文件、共享库、普通管道、命名管道、符号链接、socket流、网络socketUNIX socket,等等等等。因为UNIX世界里,几乎所有东西都是文件,所以,您可以想像lsof的用处是多么的大。

 

您可以看看本主题系列的第一篇文章,关于 pipe viewer的介绍。如果您对这篇文章感兴趣,那么请订阅我的  rss feed

 

怎样使用 lsof?

在这篇文章里,我会尽可能多地列举我能想到的用例,来说明lsof的用法。让我们从最简单的例子开始(或许您已经知道了),由浅入深地展开吧。

 

列出所有打开的文件

# lsof

不带任何参数执行lsof,就会列出所有进程打开的所有文件。

 

查找谁在使用某个文件

# lsof /path/to/file

以文件的路径为参数,lsof将会列出所有用这个文件的进程。

您也可以指定多个文件,lsof会列出所有使用这些文件的进程。

# lsof /path/to/file1 /path/to/file2

 

递归查找某个目录下所有打开的文件

# lsof +D /usr/lib

带上+D参数,lsof会在指定目录及其下所有子目录中查找找开的文件。注意这个操作效率比通常版本的grep低。

# lsof | grep ‘/usr/lib‘

之所以慢,是因为”+D”首先查找所有文件,然后再执行输出。

 

列出某个用户打开的所有文件

# lsof -u pkrumins

-u选项(认为是user)限定输出内容,只显示pkrumins用户打开的文件。您也可以同时限定多个用户,用户名之间以逗号为分隔符(译者注:逗号左右不要出现空格)

# lsof -u rms,root

这条命令会列出rms用户和root用户打开的所有文件。

另一种方式是多次使用-u选项,也能达到相同的目的:

# lsof -u rms -u root

 

按进程名查找打开的文件

# lsof -c apache

-c选项限定只列出进程名以apache打头的进程所打开的文件。因此,可以不用写:

# lsof | grep foo

而写成更简短的版本:

# lsof -c foo

事实上,您可以仅指定进程名的开头部分进行查找:

# lsof -c apa

上面这条命令将列出所有名字以apa打头的进程所打开的文件。

您还可以同时指定多个-c选项,以关联多个进程:

# lsof -c apache -c python

这条命令将会列出apachepython打开的所有文件。


译者注,对于多线程的进程来说,显示TID(Task ID)有时是必要的,但是用“-c”选项缺省是不列出子任务的,这时可以加上"-K"(大写)选项。

 

列出某个用户或进程打开的所有文件

# lsof -u pkrumins -c apache

Lsof的选项可以关联组合。缺省的关联条件是或(OR)。这意味着上面这条命令输出的内容为:列出用户pkrumins 或进程apache打开的所有文件。

 

列出某个用户与某个进程打开的所有文件

# lsof -a -u pkrumins -c bash

注意-a选项。它把关联组合的逻辑,由或(OR)变成与(AND)。所以上面这条命令输出内容为:pkrumins用户所属的,bash进程打开的所有文件。

 

列出除了root用户之外,其它用户打开的所有文件

# lsof -u ^root

注意root用户名之前的^字符。它执行取反操作。所以这条命令输出所有非root用户打开的文件。

 

列出某个PID进程打开的所有文件

# lsof -p 1

 -p(联想PID)选项,限定以进程的ID为过滤条件。记住,您可以在一个-p选项中,用逗号分隔的方式指定多个PID,也可以多次指定-p选项:

# lsof -p 450,980,333

这条命令列出PID450980333的进程打开的所有文件。

 

列出某个PID之外,其它进程打开的所有文件

# lsof -p ^1

又碰到取反操作符^了。上面这条命令列出PID 1之外的进程打开的所有文件。

 

列出所有网络连接

# lsof -i

通过-i选项lsof列出所有打开网络套接字(TCPUDP)的进程。

 

列出所有TCP网络连接

# lsof -i tcp

-i选项有几个参数,tcp就是其中之一,它限定lsof仅显示打开TCP套接字的进程。

 

列出所有UDP网络连接

# lsof -i udp

-i选项的参数值改为udp,就可以显示打开UDP套接字的进程了。

 

查找谁占用了某个端口

# lsof -i :25

-i选项的参数值改为:25lsof就会查找占用25端口的进程(包括TCPUDP)。您也可能指定端口服务名(详见/etc/services)),而不指定具体端口号:

# lsof -i :smtp

 

查找谁占用了某个UDP端口

# lsof -i udp:53

同样,查找占用的TCP端口命令为:

# lsof -i tcp:80

 

查找某个用户占用的网络端口

# lsof -a -u hacker -i

这里,-a选项关联组合了-u-i选项。上面使命列出了用户hacker所占用的网络端口。

 

列出所有NFS(网络文件系统)文件

# lsof -N

-N选项很容易记住,因为它就是NFS

 

列出所有Unix socket文件

# lsof -U

-U选项很容易记住,因为它就是UNIX

 

列出指定组ID的进程所打开的所有文件

# lsof -g 1234

进程组用于结进程进行逻辑分组。上面例子查找PGID1234的进程组成员打开的所有文件。

 

列出与某个特定文件描述符关联的所有文件

# lsof -d 2

上面这条命令,列出所有打开文件描述符2的进程。您还可以指定文件描述符的范围:

# lsof -d 0-2

这样会列出与文件描述符012关联的所有进程。

-d还选项还有许多特定参数可选,比方说mem,它列出内存映射文件:

# lsof -d mem

还有txt表示加载进内存,正在执行的进程:

# lsof -d txt

 

输出占用某些资源的进程PID

# lsof -t -i

-t选项,限定lsof仅输出进程的PID。它与-i选项组合,就只显示所有打开网络连接的进程PID。这样,如果要杀死所有使用网络的进程就很容易了:

# kill -9 `lsof -t -i`

 

循环执行lsof

# lsof -r 1

-r选项,告诉lsof不断地重复执行。参数值1表示重复周期为1秒。这

# lsof -r 1 -u john -i -a



怎样安装lsof?

许多UNIX系统都预安装了lsof。如果您的系统没有,那么到source下载源码来安装。

BSD系统有一个叫fstat的工具,实现的类似的功能。

完整的文档在 man lsof可以找到,或者通过 lsof -h查看简单的帮助。

快来体验lsof的乐趣吧!

郑重声明:本站内容如果来自互联网及其他传播媒体,其版权均属原媒体及文章作者所有。转载目的在于传递更多信息及用于网络分享,并不代表本站赞同其观点和对其真实性负责,也不构成任何其他建议。