天天看點

Linux lsof 指令

lsof(list open files)是一個檢視程序打開的檔案的工具。

在 linux 系統中,一切皆檔案。通過檔案不僅僅可以通路正常資料,還可以通路網絡連接配接和硬體。是以 lsof 指令不僅可以檢視程序打開的檔案、目錄,還可以檢視程序監聽的端口等 socket 相關的資訊。本文将介紹 lsof 指令的基本用法,本文中 demo 的示範環境為 ubuntu 18.04。

-a 訓示其它選項之間為與的關系

-c <程序名> 輸出指定程序所打開的檔案

-d <檔案描述符> 列出占用該檔案号的程序

+d <目錄>  輸出目錄及目錄下被打開的檔案和目錄(不遞歸)

+D <目錄>  遞歸輸出及目錄下被打開的檔案和目錄

-i <條件>  輸出符合條件與網絡相關的檔案

-n 不解析主機名

-p <程序号> 輸出指定 PID 的程序所打開的檔案

-P 不解析端口号

-t 隻輸出 PID

-u 輸出指定使用者打開的檔案

-U 輸出打開的 UNIX domain socket 檔案

-h 顯示幫助資訊

-v 顯示版本資訊

如果不帶任何選項執行 lsof 指令,會輸出系統中所有 active 程序打開的所有檔案,結果就是我們被輸出的資訊所淹沒,這沒有任何的意義。我們先讓 lsof 指令輸出目前 Bash 程序打開的檔案,并截取其中的一部分結果來介紹輸出内容中都包含哪些資訊:

Linux lsof 指令

COMMAND:程式的名稱

PID:程序辨別符

USER:程序所有者

FD:檔案描述符,應用程式通過檔案描述符識别該檔案

TYPE:檔案類型,如 DIR、REG 等

DEVICE:以逗号分隔裝置編号

SIZE:檔案的大小(bytes)

NODE:索引節點(檔案在磁盤上的辨別)

NAME:打開檔案的确切名稱

下面簡單介紹一下 FD 列和 TYPE 列中的常見内容。

FD 列中的常見内容有 cwd、rtd、txt、mem 和一些數字等等。其中 cwd 表示目前的工作目錄;rtd 表示根目錄;txt 表示程式的可執行檔案;mem 表示記憶體映射檔案:

Linux lsof 指令

還有一部分 FD 是以數字表示的,比如标準輸入輸出檔案:

Linux lsof 指令

數字後面的字母表示程序對該檔案的讀寫模式,比如上圖中的 u 表示該檔案被打開并處于讀取/寫入模式。除了 u,還有 r 表示隻讀模式,w 表示隻寫模式,還可以同時應用 W 表示該程序擁有對檔案寫操作的鎖。下圖是截取的 docker daemon 程序打開的檔案清單,其中顯示了 FD 的不同模式:

Linux lsof 指令

TYPE 列中常見的 REG 和 DIR 分别表示普通檔案和目錄。而 CHR 和 BLK 則分别表示字元和塊裝置,unix、fifo 和 IPv4/IPv6 分别表示 UNIX domain 套接字、先進先出(FIFO)隊列和 IPv4/IPv6 套接字。

下面我們來介紹一些 lsof 指令的常見用法。

直接指定檔案的名稱作為 lsof 的參加就可以檢視哪些程序打開了這個檔案,下面的指令查詢打開了 /bin/bash 檔案的程序:

Linux lsof 指令

除了普通檔案,也可以是裝置等檔案(下面指令的輸出很長,圖示隻是截取的一小部分):

Linux lsof 指令

這裡分兩種情況,+d 選項不執行遞歸查詢,隻查找那些打開了指定目錄以及指定目錄下檔案和目錄的程序,比如:

Linux lsof 指令

而 +D 選項則會對指定的目錄進行遞歸:

Linux lsof 指令

在解除安裝檔案系統時,如果有程序打開了該檔案系統中的檔案或目錄,解除安裝操作就會失敗。是以最好在解除安裝檔案系統前通過 lsof +D 檢查檔案系統的挂載點,殺掉相關的程序然後再執行解除安裝操作。

通過 -p 選項并指定程序的 PID 可以輸出該程序打開的所有檔案。比如我們想要檢視 cron 程式打開的檔案,可以先用 ps -C cron 指令查出程序的 PID:

Linux lsof 指令

然後把該 PID 傳遞給 lsof 指令的 -p 選項:

Linux lsof 指令

如果為 lsof 指令指定多個選項,這些選項間預設是或的關系。也就是說滿足任何一個選項的結果都會被輸出。可以添加額外的 -a 選項,它的作用就是讓其它選項之間的關系變為與,比如下面的指令:

Linux lsof 指令

其中的 -p 選項指定了目前程序的 PID,而 -d 選項則用來指定程序打開的檔案描述符(可以通過逗号分隔多個檔案描述符)。添加 -a 選項後,結果輸出為目前程序打開的檔案描述符為 0、1、2 的檔案。

說明,-a 選項的使用有很多條件,具體請參考 lsof man page。

通過 -c 選項可以比對程序運作的程式(可執行檔案)名稱。比如我們要查找以字母 cr 開頭的程式打開的檔案清單:

Linux lsof 指令

還可以同時指定多個 -c 選項,它們之間是或的關系。

如果想對 -c 選項的條件取反,隻要在字元串前添加符号 ^ 就可以了,比如:

-c 選項也支援正規表達式,比如下面的指令可以過濾出以 cra 和 cro 開頭的程式打開的檔案:

-i 選項用來檢視被打開的和網絡相關的檔案,其參數的格式如下:

[46][protocol][@hostname|hostaddr][:service|port]

46 表示 IP 協定的版本

protocol 表示網絡協定的名稱,比如 TCP 或 UDP  

hostname 或 hostaddr 表示主機位址

service 指 /etc/services 中的名稱,比如 smtp 或多個服務的清單

port 表示端口号,可以指定一個或多個

-i 選項預設會同時輸出 IPv4 和 IPv6 打開的檔案:

Linux lsof 指令

隻列出 IPv4 或 IPv6 打開的檔案

Linux lsof 指令

列出與 22 号端口相關的檔案

Linux lsof 指令

列出指定範圍内被打開的 TCP 端口

Linux lsof 指令

-U 選項輸出打開的 UNIX domain socket 檔案,這裡我們結合 -c 選項來檢視 ssh 服務打開的 UNIX domain socket 檔案:

Linux lsof 指令

-u 選項可以指定使用者名或 user ID,并且和 -c 選項一樣,可以通過逗号分隔多個使用者名稱或 user ID,也可以通過符号 ^ 對條件取反。

檢視某個使用者打開的所有檔案

Linux lsof 指令

檢視使用者 nick 打開的網絡相關的檔案

Linux lsof 指令

排除某個使用者

Linux lsof 指令

注意:在有排除條件時,不需要指定 -a 選項。

殺掉某個使用者打開了檔案的所有程序

該指令中的 -t 選項讓 lsof 指令隻輸出程序的 PID:

Linux lsof 指令
Linux lsof 指令

指令中的 -P 選項表示不解析端口号,-n 選項表示不解析主機名,這兩個選項主要的目的是為了提升 lsof 指令的執行速度。wc -l 指令則用來統計 lsof 指令輸出的行數。

如果我們一不小心删除了檔案,而又知道這個文本被某個程序打開着,就可以通過 lsof 指令來恢複該檔案。具體的原理為:

當程序打開了某個檔案時,隻要該程序保持打開該檔案,即使将檔案删除,它依然存在于磁盤中。程序并不知道檔案已經被删除,它仍然可以通過打開該檔案時提供給它的檔案描述符進行讀取和寫入。除了該程序之外,這個檔案是不可見的,因為已經删除了其相應的目錄索引節點。

程序打開的檔案描述符就存放在 /proc/PID/fd 目錄下。/proc 目錄挂載的是在記憶體中所映射的一塊區域,是以這些檔案和目錄并不存在于磁盤中,是以當我們對這些檔案進行讀取和寫入時,實際上是在從記憶體中擷取相關資訊。lsof 程式就是使用這些資訊和其他關于核心内部狀态的資訊來産生其輸出。是以 lsof 可以顯示程序的檔案描述符和相關的檔案名等資訊。也就是說我們通過通路程序的檔案描述符可以找到該檔案的相關資訊。

下面的 demo 示範如何通過 lsof 指令恢複被誤删的 /var/log/syslog 檔案。

先删除日志檔案 /var/log/syslog,記着要提前備份一下這個檔案,以防萬一:

Linux lsof 指令

從上面的資訊可以看到 PID 為 1141 的程序打開着該檔案,檔案描述符為 7,并且顯示該檔案已經被删除了。接下來我們通過 1141 号程序的檔案檔案描述符來檢視該檔案的内容:

Linux lsof 指令

上圖說明檔案 /var/log/syslog 檔案的内容還在,并且可以通過檔案描述符通路,接下來通過 IO 重定向的方式重新建立 /var/log/syslog 檔案就可以了:

然後修複檔案的權限屬性并重新開機 rsyslog 服務:

這樣就完成了 /var/log/syslog 檔案的恢複工作。對于許多應用程式,尤其是日志檔案和資料庫檔案,都可以通過這種方式來恢複。

-h 選項會輸出 lsof 指令的幫助資訊:

Linux lsof 指令

估計這樣的幫助資訊也隻能逼着你去讀 man page 了!

lsof 并不是一個簡單的指令,從其 man page 的長度就可以體會到這一點。從本文介紹的小 demo 入手或許可以讓你忘記冗長的文檔說明,一步步的開始使用并最終掌握這個指令。

參考:

lsof man page

linux lsof指令詳解

10 lsof Command Examples in Linux

Linux lsof Command Tutorial for Beginners (10 Examples)

15 Linux lsof Command Examples (Identify Open Files)

作者:sparkdev

出處:http://www.cnblogs.com/sparkdev/

本文版權歸作者和部落格園共有,歡迎轉載,但未經作者同意必須保留此段聲明,且在文章頁面明顯位置給出原文連接配接,否則保留追究法律責任的權利。

繼續閱讀