这是“您应该知道的UNIX工具系列主题文章”的第三篇。在这篇文章里,我将介绍一个很有用的工具—lsof。如果说netcat是网络连接的瑞士军刀,那么我说lsof是UNIX调试的瑞士军刀。
Lsof严格遵循UNIX的哲学典范。它仅完成一项任务,并且做得极尽完美----它能够列出某个进程所打开的文件信息。打开的文件可以是普通文件、目录、NFS文件、块文件、字符文件、共享库、普通管道、命名管道、符号链接、socket流、网络socket、UNIX
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
这条命令将会列出apache和python打开的所有文件。
译者注,对于多线程的进程来说,显示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
这条命令列出PID为450、980和333的进程打开的所有文件。
列出某个PID之外,其它进程打开的所有文件
# lsof -p ^1
又碰到取反操作符”^”了。上面这条命令列出PID
1之外的进程打开的所有文件。
列出所有网络连接
# lsof -i
通过”-i”选项,lsof列出所有打开网络套接字(TCP和UDP)的进程。
列出所有TCP网络连接
# lsof -i tcp