本篇介紹如何使用 Linux 的 lsof
指令,查詢系統上各行程所開啟的檔案。
在 Linux 系統之下,幾乎所有的系統資源都是以檔案的形式呈現的(包含一般檔案、目錄、連結檔、裝置檔、管線檔、網路 socket 等),所以對於管理者來說,若要查詢一個程式使用了哪些系統資源,就可以透過它開啟的檔案來得知。
lsof
指令可以用來查詢行程所開啟的檔案列表,這個小工具對於系統管理者來說非常實用,而且也非常重要,以下是這個工具的使用方式與範例。
直接執行 lsof
指令的話,可以列出系統上每一個行程所開啟的檔案列表:
# 列出所有行程所開啟的檔案
lsof
不過由於輸出的資料量太大了,通常我們不太會這樣使用。
如果想要查詢目前正在開啟指定檔案的行程,可以在執行 lsof
時直接加上檔案的名稱與路徑。
以 GVim 編輯器來說,當它開啟檔案進行編輯時,會自動開啟一個 .swp
的隱藏檔,我們可以使用以下指令來驗證:
# 列出所有行程所開啟的檔案
lsof .my_file.txt.swp
COMMAND PID USER FD TYPE DEVICE SIZE/OFF NODE NAME gvim 7167 gtwang 14u REG 8,6 12288 786944 .my_file.txt.swp
若要讓 lsof
列出指定用者所開啟的所有檔案,可以使用 -u
參數指定使用者名稱:
# 列出 gtwang 使用者所開啟的檔案 lsof -u gtwang
若要一次列出多位使用者所開啟的檔案,可以使用逗號分隔,或是使用多個 -u
參數來指定:
# 列出多位使用者所開啟的檔案 lsof -u user1,user2,user3 # 列出多位使用者所開啟的檔案 lsof -u user1 -u user2 -u user3
如果想要列出指定程式所開啟的檔案,可以使用 -c
參數指定程式的名稱,例如列出 httpd
這個網頁伺服器所開啟的檔案:
# 列出 httpd 伺服器所開啟的檔案 lsof -c httpd
若要列出多個程式所開啟的檔案,可以使用多個 -c
參數來指定:
# 列出多個程式所開啟的檔案 lsof -c java -c httpd
lsof
可以同時指定多個篩選條件,預設的狀況下多個條件之間會以 OR 運算來結合,假設我們想要列出 root
使用者所開啟的檔案,或是 java
這個應用程式所開啟的檔案,就可以這樣寫:
# 多個條件(OR 運算) lsof -u root -c java
而如果我們想要以 AND 運算來結合多個條件,可加上 -a
參數。例如若要列出 root
使用者執行 java
程式所開啟的檔案,可以這樣寫:
# 多個條件(AND 運算) lsof -a -u root -c java
如果想要排除特定的使用者所開啟的檔案,可以在使用者名稱之前加上 ^
符號:
# 列出非 root 使用者所開啟的檔案 lsof -u ^root
這樣就會列出除了 root
之外,所有使用者所開啟的檔案。
若要列出指定 PID 的行程所開啟的檔案,可以使用 -p
參數來指定 PID:
# 列出 PID 為 14662 的行程,所開啟的檔案 lsof -p 14662
若要同時根據多個 PID 列出開啟的檔案,一樣可以用逗號分隔多個 PID:
# 根據多個 PID 列出開啟的檔案 lsof -p 14662,14678,14979
lsof
的 -i
參數可以用來查詢所有的網路連線:
# 列出所有網路連線 lsof -i
若想只想要列出 TCP 或 UDP 的網路連線,可以在 -i
參數之後指定 tcp
或 udp
:
# 列出所有 TCP 網路連線 lsof -i tcp # 列出所有 UDP 網路連線 lsof -i udp
亦可指定連接埠,例如列出網頁伺服器的網路連線:
# 列出 80 連接埠的網路連線 lsof -i :80
這是一些其他的範例:
# 列出 SMTP 的網路連線 lsof -i :smtp # 列出 3642 連接埠的 TCP 連線 lsof -i tcp:3642 # 列出 1 到 1024 連接埠的 TCP 網路連線 lsof -i :1-1024
若要列出所有處於 LISTEN
狀態的 TCP
網路連線,可以執行:
# 列出所有處於 LISTEN 狀態的 TCP 網路連線 lsof -i TCP -s TCP:LISTEN
列出已建立的 TCP 網路連線:
# 列出已建立的 TCP 網路連線 lsof -i TCP -s TCP:ESTABLISHED
參考資料:Javarevisited、HowtoForge、Daniel Miessler、Linux Handbook