有沒有想過如何找出系統上當前打開和正在使用的文件? 他 Linux lsof 命令列出打開的文件並提供大量附加信息。 通過這些實際示例了解如何使用 lsof。
lsof是什麼?
在任何本地可用 Linux 操作系統, lsof
該命令提供打開文件的列表。 但是,輸出可能有點神秘且較長,特別是當在給定係統上使用許多應用程序時。 讓我們看一下基礎知識。 lsof
生產。 我們將跑步 lsof
作為根。
要以 root 身份登錄,您可以打開終端窗口並鍵入如下命令 sudo su
哦 su
接收 root 身份驗證提示。 或者你可以運行 sudo lsof
。 請注意,雖然您可以運行 lsof
作為普通的非 root 用戶,輸出可能不完整。
示例:基本 lsof 輸出
sudo su lsof | head -n10
這裡我們使用以下命令啟動 lsof 工具 lsof
命令,並使用管道捕獲輸出的前十行(|
)發送信息輸出 lsof
到高中 head -n10
僅捕獲前十(頭)行的命令。
他 lsof
該命令列出多列。 我們首先看到 COMMAND 列,其中列出了包含打開文件/打開文件鎖的二進製文件。 接下來我們看到 PID 進程 ID 列,該列在嘗試調試各種應用程序問題(包括不正確地持有文件鎖)時非常有用。 在下一節中,我們將討論 example 我們如何使用 lsof
結合 kill
(破壞性地)終止包含錯誤文件鎖的應用程序。
如果您的操作系統支持,TID 列可以幫助您確定給定的行是進程還是任務。 如果輸出為空,如我們的中所示 example (它正在運行 Linux Mint,一個支持TID列輸出的操作系統),給定的行/命令是一個進程,而不是一個任務。 例如,如果您在操作系統上啟動計算器應用程序(即任務),則此列將填充任務/線程 ID 號。
TASKCMD 列包含任務命令的名稱。 同樣,僅當給定的行是任務而不是進程時,它才可見。 這通常與 COMMAND 第一列中顯示的命令/過程相同,但是,對於 example, Linux 允許任務更改其命令名稱,因此它可以包含有關該任務的附加信息。 USER 列列出了啟動進程/任務的用戶。
接下來,我們有一個重要的 FD(文件描述符)列,它可以列出文件描述符編號或指示文件描述符類型的特定文本字符串。 例如,如果您看到 cwd
在此列中,代表當前工作目錄,並指示給定進程或任務在當前工作目錄中具有打開的鎖,並且該工作目錄出現在 NAME 列中。
有關所有可能的完整列表 FD
鏈條類型 man lsof
在命令提示符下鍵入 / FD
(斜線後、FD 前有 3 個空格)進入手冊後,按 ENTER 鍵查找 FD 部分。
在處理常規文件時,您可以將 FD 列視為計數器或唯一 ID 計數器,從 0 開始並增加到系統上常規打開文件的總數,最大打開文件數由設置 ulimit 定義-n 等
當查看常規文件時,FD 列將用於 example 展示 102u
哦 13w
。 這兩個示例分別代表系統上第 102 個打開的文件,處於混合讀/寫訪問模式,如下所示 u
flag/label 和第 13 個文件在系統上僅以寫訪問模式打開。
TYPE 列是不言自明的; 指示是否持有常規文件或目錄打開鎖。 這裡可能會顯示其他幾個標籤,並且搜索 / TYPE
在 man lsof
(如上所述)將提供完整的列表。
DEVICE 列通常列出大多數文件類型的設備編號,以逗號分隔。 他 SIZE/OFF
該列是文件大小,或以字節為單位的文件偏移量,NODE 列通常顯示本地文件的文件節點號或 NFS 文件 inode 號。 您還可以列出 example TCP 或 UDP(當提供的鎖是開放的 Internet 連接時)。
示例:將 lsof 與 Kill 結合使用
使用 lsof
結合 grep
, awk
y kill
人們可以在給定係統中搜索特定文件,然後終止該進程(使用如上所述的 PID 或進程標識符)。
請注意,只有在有意義的情況下才應該這樣做。 為了 example,您可能有一個多線程 Bash 腳本,它啟動許多不同的子 shell,其中每個子 shell 都掛起一個給定的文件,並等待其中一個線程掛起。 您知道阻塞進程的打開文件名,但不知道該進程/任務的 PID 是什麼。
在這種情況下,我們可以運行以下命令:
sudo su lsof | grep 'some_file_descriptor' | awk '{print $2}' | xargs -I{} kill -9 {}
讓我們將其付諸實踐 example。 假設我們創建了以下腳本 test.sh
在 /tmp
:
rm -Rf workspace mkdir workspace cd workspace sleep 36000
該腳本執行時將創建一個名為的目錄 workspace
更改其上的目錄 cd
進而 sleep
10小時。 雖然乍一看這可能不會打開任何文件,但請記住 cwd
之前討論過; 該腳本有一個正在使用的當前工作目錄,即 /tmp/workspace
!
讓我們看看這在實踐中是如何運作的。 首先,我們定義(使用您最喜歡的文本編輯器,例如 vi
),然後在終端會話中啟動腳本:
然後我們跳到輔助/新終端會話並運行 lsof
尋找腳本的工作目錄,即 workspace
:
正如我們所看到的, lsof
不僅能夠找到我們的測試腳本 test.sh
你拿著一個 cwd
伴侶 /tmp/workspace
但我們也看到 sleep
從腳本內部開始,你拿著一個 cwd
在同一目錄中打開文件描述符(或更好的目錄)。
我們還可以看到 PID test.sh
腳本,以及 sleep
領域。 假設我們的 test.sh
腳本掛起,我們想徹底破壞性地殺死它,即 kill -9
這是在沒有任何正常關閉級別的情況下終止進程的最具破壞性的方法,並且這是基於腳本包含的打開文件(或在我們的例子中,打開目錄)。 我們從輔助終端發出以下命令:
lsof | grep "workspace" | awk '{print $2}' | xargs -I{} kill -9 {}
該命令將獲取先前的輸出並進一步解析它。 他 awk '{print $2}'
它基本上從第二列(進程 ID)和 xargs
命令將把第二列傳遞給 kill -9
(他 {}
命令中的內容將被任何輸入替換 xargs
收到)。
我們也可以預見到 lsof
有一個標題行包含 PID
而這段文字也將被傳殺。 雖然它不會產生問題,但更好的通用命令應該是 lsof | grep "workspace" | grep -v "PID" | awk '{print $2}' | xargs -I{} kill -9 {}
或其他方式來完全過濾第一行。
我們的第一個/主要終端會話的結果是我們的腳本立即被終止:
如果您想了解有關 xargs 的更多信息,您可以閱讀結合使用 xargs bash -c 創建複雜命令。 有關 Bash 多線程編程,請參閱如何在 Bash 腳本中使用多線程處理。
結尾
在本文中,我們探討了使用 lsof
、列出打開文件命令,以及每列在其默認輸出中代表什麼信息。 我們還研究了一個實際用例,其中我們使用 lsof
結合 grep
, awk
y kill
查找由腳本保持打開狀態的特定文件(或者在我們的例子中為目錄),然後結束該腳本,從而關閉打開的目錄。
如果您喜歡閱讀本文,請看一下我們的斷言、錯誤和崩潰:有什麼區別? 文章。