轉自:http://blog.csdn.net/yetyongjin/article/details/7740373
這是“您應該知道的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
”-i”選項有幾個參數,”tcp”就是其中之一,它限定lsof僅顯示打開TCP套接字的進程。
列出所有UDP網絡連接
# lsof -i udp
”-i”選項的參數值改爲”udp”,就可以顯示打開UDP套接字的進程了。
查找誰佔用了某個端口
# lsof -i :25
”-i”選項的參數值改爲”:25”,lsof就會查找佔用25端口的進程(包括TCP和UDP)。您也可能指定端口服務名(詳見/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
進程組用於結進程進行邏輯分組。上面例子查找PGID爲1234的進程組成員打開的所有文件。
列出與某個特定文件描述符關聯的所有文件
# lsof -d 2
上面這條命令,列出所有打開文件描述符2的進程。您還可以指定文件描述符的範圍:
# lsof -d 0-2
這樣會列出與文件描述符0、1、2關聯的所有進程。
“-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的樂趣吧!