Linux 命令(124)—— lsof 命令
- 2020 年 2 月 26 日
- 筆記
1.命令簡介
lsof(list open files)用於查看進程打開的文件,是十分方便的系統監測工具。因為 lsof 命令需要訪問核心內存和各種系統文件,所以需要 root 權限才可執行。
在 Linux 系統中,一切皆文件。通過文件不僅僅可以訪問常規數據,還可以訪問網絡連接和硬件。所以 lsof 不僅可以查看進程打開的普通文件、目錄,還可以查看進程監聽的端口等 socket 相關的信息。進程打開的每一個文件,系統在後台都會為之分配一個文件描述符,無論這個文件的本質如何,該文件描述符為應用程序與基礎操作系統之間的交互提供了通用接口。因為應用程序打開文件的描述符列表提供了大量關於這個應用程序本身的信息,因此通過 lsof 工具能夠查看這個列表,對系統監測以及排錯很有幫助。
lsof 查看的打開文件可以是:
普通文件 目錄 字符或塊設備文件 共享庫 管道、命名管道 符號鏈接 網絡文件(如 NFS file、網絡 socket,Unix 域名 socket) 其它類型的文件,等等
2.命令格式
lsof [OPTIONS] [--] [NAMES]
在沒有任何選項的情況下,lsof 列出所有屬於活動進程的打開文件。
3.選項說明
-?, -h 顯示幫助信息 -a 參數被視為邏輯與 AND,會影響全部的參數 -A A 在配置了 AFS 分佈式網絡文件系統的系統上可用,其 AFS 內核代碼是通過動態模塊實現的。通過 A 指定備用名稱列表文件,在該文件中可以找到動態模塊的內核地址 -b 避免 lsof 因調用可能阻塞的內核函數而產生阻塞,比如 lstat(2)、readlink(2) 和 stat(2) 等內核函數 -c C 顯示出以字符或字符串 C 開頭的命令程序開啟的文件,如 lsof -c init。如果 C 以斜杠 / 開頭和結尾,則斜杠之間的字符被解釋為正則表達式。該選項可多次指定 +c W 指定 COMMAND 列的寬度,單位字符。默認為 9 -C 禁用從內核的名稱緩存中報告任何路徑名 -D D 指導 lsof 使用設備緩存文件。該選項的使用有時受到限制。-D 必須後面跟着一個函數字母,函數字母后面可以有一個路徑名稱。lsof 識別以下功能字母: ? 報告設備緩存文件路徑 b 構建設備緩存文件 i 忽略設備緩存文件 r 讀取設備緩存文件 u 讀取並更新設備緩存文件 +D D 遞歸搜索目錄 D。如顯示在 /usr/local 及其子目錄下被程序開啟的文件:lsof +D /usr/local +d D 非遞歸搜索目錄 D。如顯示在 /usr/local 下被程序開啟的文件:lsof +d /usr/local -d FD 指定文件描述符列表,可以採用逗號分隔,也可以指定範圍。比如 1,2,3 或 1-3。如果前面包含尖號,表示排除。如顯示 FD 為 4 的進程:lsof -d 4 +|-e S 豁免(exempt)路徑名稱為 S 的文件系統不受可能阻塞的內核函數調用的影響。+e 選項豁免 stat(2)、lstat(2) 和大多數 readlink(2) 內核函數調用。-e 選項只能豁免 stat(2) 和 lstat(2) 內核函數調用 +|-E +E 指定使用端點信息顯示 Linux 管道、Linux UNIX 套接字和 Linux 偽終端文件,並顯示端點的文件。-E 則不顯示端點的文件 -F LIST 指定字符列表 LIST,選擇輸出給另一程序處理的字段,各字段對應的字符見下文 +|-f [cfgGn] f 本身澄清了路徑名參數的解釋方式。當後面跟着 c、f、g、G 或 n 時,它指定要啟用(+)或抑制(-)內核文件結構信息。 c 文件結構使用計數(not Linux) f 文件結構地址(not Linux) g 文件標誌縮寫(Linux 2.6.22 及更高版本) G 十六進制文件標誌(Linux 2.6.22 及更高版本) n 文件結構節點地址(not Linux) -g [PGID] 選擇或排除屬於指定進程組的進程打開的文件。 進程組 ID 使用逗號分隔,如果 PGID 前面包含尖號,表示排除。若沒有指定 PGID,則顯示全部。如顯示 PGID 為 6 和 7 的進程:lsof -g6,7 -i [I] 選擇其 Internet 地址與 -i 中指定的地址匹配的文件,若沒有相關地址被指定,則監聽全部。 用法: lsof -i [46][protocol][@hostname|hostaddr][:serivce|port] 說明:4 6 分別表示 IPv4 和 IPv6 protocol: TCP or UDP hostname:主機名 hostaddr:IPv4 或 IPv6 地址 service:主機提供的服務的名稱,即 /etc/services 中的 service name port:端口號 -K 在支持任務(線程)報告方式的系統上輸出進程的任務(線程)列表 -k K 指定內核名稱列表文件,代替 /vmunix、/mach 等 -l 禁止將 user ID 轉換為登錄的名稱,默認是登錄名稱 +|-L [L] + 或 - 表示開啟或關閉顯示文件連接數,如果只有單純的 +L,後面沒有任何數字,則表示顯示全部,如果後面有數字,只有文件連接數少於該數字的會被列出 +|-m M -m 指定一個內核內存文件 M ,代替 /dev/kmem 或 /dev/mem。+m 將裝載補充文件寫入標準輸出文件 +|-M 啟用或禁用報告本地 TCP、UDP 和 UDPLITE 端口的端口映射器註冊 -n 不將 IP 地址轉換為主機名 -N 顯示 NFS 文件 -o 始終顯示文件偏移量。它導致 SIZE/OFF 輸出列標題更改為 OFFSET -o O 指定在文件偏移量的 0t 之後要打印的小數位數 -O 指示 lsof 避免被某些內核操作阻塞。即在分叉的子進程中執行它們。雖然使用此選項將減少 lsof 啟動開銷,但也可能導致 lsof 在內核不響應函數時掛起。謹慎使用此選項 -P 禁止將網絡文件的端口號轉換為端口名 -p S 排除或選擇進程的文件列表,進程 ID 列表使用逗號分隔,如 123 或 123,^456。尖號表示排除指定 PID -R 使用列 PPID 列出父進程的 PID +|-r [T[mFMT]] 控制 lsof 不斷重複執行,間隔 T 秒,默認為 15s。-r 永遠不斷地執行,直到收到中斷訊號(ctrl+ c),+r 一直執行,直到沒有文件被顯示。可選的 mFMT 參數指定標記線的格式,格式 FMT 遵循 C 語言標準庫函數 strftime(3) 的規範 -S [T] 指定內核函數 lstat(2)、readlink(2) 和 stat(2) 的可選超時秒值,否則可能會死鎖。t 的最小值是 2;默認值是 15 -s [P:S] 列出文件的大小,若該文件沒有大小,則留下空白。它導致 SIZE/OFF 輸出列標題更改為 SIZE。P 表示協議名稱 TCP or UDP,S 表示逗號分隔的協議狀態 -T [T] -T 沒有參數則禁用 TCP/TPI 信息報告。跟如下參數,則顯示指定 TCP/TPI 信息: f 選擇報告套接字選項,狀態和值,以及 TCP標誌和值 q 選擇隊列長度 s 選擇連接狀態 w 選擇窗口大小 -t 生成只有進程標識符而沒有標題的簡潔輸出,這樣輸出可以通過管道傳遞給 kill(1) 殺死 -U 選擇 UNIX 域套接字文件的列表 -u USERS 選擇登錄名或用戶 ID 位於逗號分隔集 USERS 中的用戶的文件列表。如 root 或 548,root」,如果用戶名或用戶 ID 前有尖號 ^,表示排除 -V 指示被要求列出但找不到的項 -v 顯示版本信息 +|-w 啟用(+)或禁用(-)警告消息 -X Linux 下跳過所有打開的 TCP、UDP 和 UDPLITE IPv4 和 IPv6 文件的信息報告 -x [fl] 一般與選項 +d 和 +D 選項,指示搜索時是否跨文件系統和符號鏈接。-x 不跟任何參數時,表示跨文件系統和符號鏈接 -Z [Z] 指定如何處理 SELinux 安全上下文。當在運行的 Linux 內核中禁用SELinux時,Z 字段將被抑制輸出。-Z 選項不跟參數,如 -Z -,安全上下文將列在 SECURITY-CONTEXT 列中輸出 -- 雙減號表示選項結束 NAMES 列出指定文件,符號鏈接在使用前將被解析
4.輸出字段說明
當指定了 -F 選項時,lsof 將生成適合由另一個程序(如 awk 或 Perl 腳本或 C 程序)處理的輸出。
下面是 lsof 可輸出的字段。單個字符表示字段標識符。
a 文件訪問模式 c 進程命令名 C 文件結構共享計數 d 文件的設備字符碼 D 文件的主要/次要設備號 F 文件結構地址 f 文件描述符 G 文件標誌 g 進程組 ID i 文件 inode 編號 K 任務 ID k 鏈接計數 L 進程登錄名 m 重複輸出之間的標記 N 節點標識符 n 文件名、注釋、Internet 地址 o 文件偏移量(十進制) P 協議名稱 p 進程 ID R 父進程 ID r 原始設備號 S 文件的流標識 s 文件大小(十進制) T TCP/TPI 信息 t 文件類型 u 進程用戶 ID Z SELinux 安全上下文(禁用 SELinux 時禁用) z Solaris 10 及更高版本的區域名 0 使用NUL字段結束符字符代替NL 1-9 系統特定的字段標識符
可以使用命令 lsof -F?
查看上面字段的說明信息。
5.常用示例
(1)無任何參數,列出所有屬於活動進程的打開文件。
lsof | head COMMAND PID TID USER FD TYPE DEVICE SIZE/OFF NODE NAME systemd 1 root cwd DIR 252,1 4096 2 / systemd 1 root rtd DIR 252,1 4096 2 / systemd 1 root txt REG 252,1 1616248 47908 /usr/lib/systemd/systemd systemd 1 root mem REG 252,1 20032 25897 /usr/lib64/libuuid.so.1.3.0 systemd 1 root mem REG 252,1 252704 25043 /usr/lib64/libblkid.so.1.1.0 systemd 1 root mem REG 252,1 90632 25988 /usr/lib64/libz.so.1.2.7 systemd 1 root mem REG 252,1 153192 25496 /usr/lib64/liblzma.so.5.0.99 systemd 1 root mem REG 252,1 23968 25065 /usr/lib64/libcap-ng.so.0.0.0 systemd 1 root mem REG 252,1 19888 25018 /usr/lib64/libattr.so.1.1.0
lsof 輸出各列信息的意義如下:
COMMAND:進程的名稱 PID:進程標識符 TID:任務 ID。Linux 下 TID 為空表示該行為進程 USER:進程所有者 FD:文件描述符。主要有: cwd:應用程序當前工作目錄,這是該應用程序啟動的目錄,除非它本身對這個目錄進行更改 txt:該類型的文件是程序代碼,如應用程序二進制文件本身或共享庫,如上列表中顯示的 /sbin/init 程序 lnn:庫引用(AIX) err:FD 信息錯誤 jld:監獄目錄(FreeBSD) ltx:共享庫文本(代碼和數據) mxx:十六進制內存映射類型號 xx m86:DOS合併映射文件 mem:內存映射文件 mmap:內存映射設備 pd:父目錄 rtd:根目錄 tr:內核跟蹤文件(OpenBSD) v86:VP/ix 映射文件 0:標準輸出 1:標準輸入 2:標準錯誤 文件描述符後一般還跟着文件狀態模式: r:只讀模式 w:寫入模式 u:讀寫模式 空格:文件的狀態模式為 unknow,且沒有鎖定 -:文件的狀態模式為 unknow,且被鎖定 同時在文件狀態模式後面,還跟着相關的鎖: N:對於未知類型的 Solaris NFS 鎖 r:文件部分的讀鎖 R:整個文件的讀鎖 w:文件的部分寫鎖 W:整個文件的寫鎖 u:任何長度的讀寫鎖 U:用於未知類型的鎖 x:用於部分文件上的 SCO OpenServer Xenix 鎖 X:用於整個文件上的 SCO OpenServer Xenix 鎖 space:無鎖 TYPE:文件類型。常見的文件類型有: REG:普通文件 DIR:表示目錄 CHR:表示字符類型 BLK:塊設備類型 UNIX:UNIX 域套接字 FIFO:先進先出隊列 IPv4:IPv4 套接字 DEVICE:磁盤名稱 SIZE:文件的大小或文件偏移量(以位元組為單位) NODE:索引節點 NAME:打開文件的確切名稱
(2)查看誰正在使用某個文件,也就是說查找某個文件相關的進程。
lsof /bin/bash COMMAND PID USER FD TYPE DEVICE SIZE/OFF NODE NAME watchdog. 7639 root txt REG 252,1 922760 45210 /usr/bin/bash bash 8591 root txt REG 252,1 922760 45210 /usr/bin/bash bash 9694 root txt REG 252,1 922760 45210 /usr/bin/bash bash 20151 root txt REG 252,1 922760 45210 /usr/bin/bash
(3)遞歸查看某個目錄下所有被打開的文件信息。
lsof +D ./test COMMAND PID USER FD TYPE DEVICE SIZE/OFF NODE NAME bash 8518 root cwd DIR 252,1 4096 799036 ./test/shell
(4)列出某個用戶打開的文件信息。
lsof -u root
(5)列出某個進程所打開的文件信息。
lsof -c sshd
-c 選項將會列出所有以 sshd 開頭的進程所打開的文件。其實也可以通過命令lsof | grep sshd
來查看,但是第一種方法更加簡潔。
(6)列出多個進程打開的文件信息。
lsof -c mysql -c apache
(7)列出某個用戶以及某個進程所打開的文件信息。
lsof -u test -c mysql
注意,-u 與 -c 選項之間是或的關係。可以使用 –
(8)列出除了某個用戶外的所有被打開的文件信息。
lsof -u ^root
尖號 ^ 在用戶名之前,表示排除在外,即不顯示 root 用戶所打開的文件信息。
(9)通過某個進程號顯示該進程打開的文件。
lsof -p 1
(10)列出多個進程號對應的文件信息。
lsof -p 1,2,3
(11)列出除了某個進程號,其他進程號所打開的文件信息。
lsof -p ^1
(12)列出所有的網絡連接。
lsof -i
(13)列出所有的 TCP 網絡連接信息。
lsof -i tcp
(14)列出所有 UDP 網絡連接信息。
lsof -i udp
(15)列出誰在使用某個端口。
lsof -i :3306
(16)列出誰在使用某個特定的 UDP 或 TCP 端口。
lsof -i udp:55 lsof -i tcp:80
(17)列出某個用戶的所有活躍的網絡端口。
lsof -a -u test -i
(18)列出所有網絡文件系統。
lsof -N
(19)選擇 UNIX 域套接字文件的列表。
lsof -U
(20)查看某個用戶組所打開的文件信息。
lsof -g 5555
(21)根據指定文件描述符的文件信息。
lsof -d txt lsof -d 1 lsof -d 2
0 表示標準輸入,1 表示標準輸出,2 表示標準錯誤,從而可知:所以大多數應用程序所打開的文件的 FD 都是從 3 開始。
(22)查看指定文件描述符範圍的文件信息。
lsof -d 2-3
(23)列出 COMMAND 列中包含字符串 sshd 且文件描符的類型為 txt 的文件信息。
lsof -c sshd -a -d txt COMMAND PID USER FD TYPE DEVICE SIZE/OFF NODE NAME sshd 8254 root txt REG 252,1 819608 27632 /usr/sbin/sshd sshd 20149 root txt REG 252,1 819608 27632 /usr/sbin/sshd
(24)列出被進程號為 1234 的進程所打開的所有 IPV4 網絡文件。
lsof -p 1234 -a -i 4
(25)列出目前連接主機 peida.linux 上端口為:20,21,22,25 相關的所有文件信息,且每隔 3 秒不斷地執行 lsof 指令。
lsof -i @peida.linux:20,21,22,25 -r 3
參考文獻
[1] lsof(8) manual [2] 百度百科.Andrew文件系統 [3] 博客園.每天一個linux命令(51):lsof命令