Linux lsof命令解析

svoid發表於2016-03-06

lsof簡介

lsof(list open files)是一個列出當前系統開啟檔案的工具。在linux環境下,任何事物都以檔案的形式存在,通過檔案不僅僅可以訪問常規資料,還可以訪問網路連線和硬體。所以如傳輸控制協議 (TCP) 和使用者資料包協議 (UDP) 套接字等,系統在後臺都為該應用程式分配了一個檔案描述符,無論這個檔案的本質如何,該檔案描述符為應用程式與基礎作業系統之間的互動提供了通用介面。因為應用程式開啟檔案的描述符列表提供了大量關於這個應用程式本身的資訊,因此通過lsof工具能夠檢視這個列表對系統監測以及排錯將是很有幫助的。

輸出資訊含義

在終端下輸入lsof即可顯示系統開啟的檔案,因為 lsof 需要訪問核心記憶體和各種檔案,所以必須以 root 使用者的身份執行它才能夠充分地發揮其功能。

  1. 輸出示例:
  2. mysqld_sa 9741 root cwd DIR 8,2 4096 396 /opt/mysql
  3. mysqld_sa 9741 root rtd DIR 8,2 4096 2 /
  4. mysqld_sa 9741 root txt REG 8,2 938768 284 /bin/bash (deleted)
  5. mysqld_sa 9741 root mem REG 8,2 65928 64 /lib64/libnss_files-2.12.so
  6. mysqld_sa 9741 root DEL REG 8,2 48 /lib64/libc-2.12.so
  7. mysqld_sa 9741 root DEL REG 8,2 54 /lib64/libdl-2.12.so
  8. mysqld_sa 9741 root DEL REG 8,2 92 /lib64/libtinfo.so.5.7.#prelink#.aSxl61
  9. mysqld_sa 9741 root DEL REG 8,2 16 /lib64/ld-2.12.so
  10. mysqld_sa 9741 root 0r CHR 1,3 0t0 3698 /dev/null
  11. mysqld_sa 9741 root 1w CHR 1,3 0t0 3698 /dev/null
  12. mysqld_sa 9741 root 2w CHR 1,3 0t0 3698 /dev/null
  13. mysqld_sa 9741 root 255r REG 8,2 25366 178656 /opt/mysql/bin/mysqld_safe
  14. mysqld 10176 mysql cwd DIR 8,5 4096 392449 /data/mysql_data
  15. mysqld 10176 mysql rtd DIR 8,2 4096 2 /
  16. mysqld 10176 mysql txt REG 8,2 251557516 178640 /opt/mysql/bin/mysqld
  17. mysqld 10176 mysql mem REG 8,2 5624 1185 /lib64/libaio.so.1.0.1
  18. mysqld 10176 mysql DEL REG 8,2 4443 /lib64/libfreebl3.so
  19. mysqld 10176 mysql mem REG 8,2 65928 64 /lib64/libnss_files-2.12.so
  20. mysqld 10176 mysql DEL REG 8,2 48 /lib64/libc-2.12.so
  21. mysqld 10176 mysql DEL REG 8,2 1177 /lib64/libgcc_s-4.4.7-20120601.so.1.#prelink#.T8xF9n
  22. mysqld 10176 mysql DEL REG 8,2 56 /lib64/libm-2.12.so
  23. mysqld 10176 mysql DEL REG 8,2 134912 /usr/lib64/libstdc++.so.6.0.13.#prelink#.goR9gv
  24. mysqld 10176 mysql DEL REG 8,2 76 /lib64/librt-2.12.so
  25. mysqld 10176 mysql DEL REG 8,2 54 /lib64/libdl-2.12.so
  26. mysqld 10176 mysql DEL REG 8,2 52 /lib64/libcrypt-2.12.so.#prelink#.7FEVsY
  27. mysqld 10176 mysql DEL REG 8,2 72 /lib64/libpthread-2.12.so.#prelink#.Bl3jz2
  28. mysqld 10176 mysql DEL REG 8,2 16 /lib64/ld-2.12.so
  29. mysqld 10176 mysql 0r CHR 1,3 0t0 3698 /dev/null

每行顯示一個開啟的檔案,若不指定條件預設將顯示所有程式開啟的所有檔案。

lsof輸出各列資訊的意義如下:

  • COMMAND:程式的名稱
  • PID:程式識別符號
  • USER:程式所有者
  • FD:檔案描述符,應用程式通過檔案描述符識別該檔案。如cwd、txt等
  • TYPE:檔案型別,如DIR、REG等
  • DEVICE:指定磁碟的名稱
  • SIZE:檔案的大小
  • NODE:索引節點(檔案在磁碟上的標識)
  • NAME:開啟檔案的確切名稱

FD 列中的檔案描述符cwd 值表示應用程式的當前工作目錄,這是該應用程式啟動的目錄,除非它本身對這個目錄進行更改,txt 型別的檔案是程式程式碼,如應用程式二進位制檔案本身或共享庫,如上列表中顯示的 /sbin/init 程式。

其次數值表示應用程式的檔案描述符,這是開啟該檔案時返回的一個整數。如上的最後一行檔案/dev/initctl,其檔案描述符為 10。u 表示該檔案被開啟並處於讀取/寫入模式,而不是隻讀 ? 或只寫 (w) 模式。同時還有大寫 的W 表示該應用程式具有對整個檔案的寫鎖。該檔案描述符用於確保每次只能開啟一個應用程式例項。初始開啟每個應用程式時,都具有三個檔案描述符,從 0 到 2,分別表示標準輸入、輸出和錯誤流。所以大多數應用程式所開啟的檔案的 FD 都是從 3 開始。

與 FD 列相比,Type 列則比較直觀。檔案和目錄分別稱為 REG 和 DIR。而CHR 和 BLK,分別表示字元和塊裝置;或者 UNIX、FIFO 和 IPv4,分別表示 UNIX 域套接字、先進先出 (FIFO) 佇列和網際協議 (IP) 套接字。

常用引數

  1. lsof abc.txt 顯示開啟檔案abc.txt的程式
  2. lsof -c abc 顯示abc程式現在開啟的檔案
  3. lsof -c -p 1234 列出程式號為1234的程式所開啟的檔案
  4. lsof -g gid 顯示歸屬gid的程式情況
  5. lsof +d /usr/local/ 顯示目錄下被程式開啟的檔案
  6. lsof +D /usr/local/ 同上,但是會搜尋目錄下的目錄,時間較長
  7. lsof -d 4 顯示使用fd4的程式
  8. lsof -i 用以顯示符合條件的程式情況
  9. lsof -i[46] [protocol][@hostname|hostaddr][:service|port]
  10. 46 --> IPv4 or IPv6
  11. protocol --> TCP or UDP
  12. hostname --> Internet host name
  13. hostaddr --> IPv4地址
  14. service --> /etc/service中的 service name (可以不止一個)
  15. port --> 埠號 (可以不止一個)

lsof使用例項

查詢誰在使用檔案系統

在解除安裝檔案系統時,如果該檔案系統中有任何開啟的檔案,操作通常將會失敗。那麼通過lsof可以找出那些程式正在使用當前要解除安裝的檔案系統,如下:

  1. # lsof /GTES11/
  2. COMMAND PID USER FD TYPE DEVICE SIZE NODE NAME
  3. bash 4208 root cwd DIR 3,1 4096 2 /GTES11/
  4. vim 4230 root cwd DIR 3,1 4096 2 /GTES11/

在這個示例中,使用者root正在其/GTES11目錄中進行一些操作。一個 bash是例項正在執行,並且它當前的目錄為/GTES11,另一個則顯示的是vim正在編輯/GTES11下的檔案。要成功地解除安裝/GTES11,應該在通知使用者以確保情況正常之後,中止這些程式。 這個示例說明了應用程式的當前工作目錄非常重要,因為它仍保持著檔案資源,並且可以防止檔案系統被解除安裝。這就是為什麼大部分守護程式(後臺程式)將它們的目錄更改為根目錄、或服務特定的目錄(如 sendmail 示例中的 /var/spool/mqueue)的原因,以避免該守護程式阻止解除安裝不相關的檔案系統。

恢復刪除的檔案

當Linux計算機受到入侵時,常見的情況是日誌檔案被刪除,以掩蓋攻擊者的蹤跡。管理錯誤也可能導致意外刪除重要的檔案,比如在清理舊日誌時,意外地刪除了資料庫的活動事務日誌。有時可以通過lsof來恢復這些檔案。
當程式開啟了某個檔案時,只要該程式保持開啟該檔案,即使將其刪除,它依然存在於磁碟中。這意味著,程式並不知道檔案已經被刪除,它仍然可以向開啟該檔案時提供給它的檔案描述符進行讀取和寫入。除了該程式之外,這個檔案是不可見的,因為已經刪除了其相應的目錄索引節點。
在/proc 目錄下,其中包含了反映核心和程式樹的各種檔案。/proc目錄掛載的是在記憶體中所對映的一塊區域,所以這些檔案和目錄並不存在於磁碟中,因此當我們對這些檔案進行讀取和寫入時,實際上是在從記憶體中獲取相關資訊。大多數與 lsof 相關的資訊都儲存於以程式的 PID 命名的目錄中,即 /proc/1234 中包含的是 PID 為 1234 的程式的資訊。每個程式目錄中存在著各種檔案,它們可以使得應用程式簡單地瞭解程式的記憶體空間、檔案描述符列表、指向磁碟上的檔案的符號連結和其他系統資訊。lsof 程式使用該資訊和其他關於核心內部狀態的資訊來產生其輸出。所以lsof 可以顯示程式的檔案描述符和相關的檔名等資訊。也就是我們通過訪問程式的檔案描述符可以找到該檔案的相關資訊。
當系統中的某個檔案被意外地刪除了,只要這個時候系統中還有程式正在訪問該檔案,那麼我們就可以通過lsof從/proc目錄下恢復該檔案的內容。 假如由於誤操作將/var/log/messages檔案刪除掉了,那麼這時要將/var/log/messages檔案恢復的方法如下:
首先使用lsof來檢視當前是否有程式開啟/var/logmessages檔案,如下:

  1. # lsof |grep /var/log/messages
  2. syslogd 1283 root 2w REG 3,3 5381017 1773647 /var/log/messages (deleted)

從上面的資訊可以看到 PID 1283(syslogd)開啟檔案的檔案描述符為 2。同時還可以看到/var/log/messages已經標記被刪除了。因此我們可以在 /proc/1283/fd/2 (fd下的每個以數字命名的檔案表示程式對應的檔案描述符)中檢視相應的資訊,如下:

  1. # head -n 10 /proc/1283/fd/2
  2. Aug 4 13:50:15 holmes86 syslogd 1.4.1: restart.
  3. Aug 4 13:50:15 holmes86 kernel: klogd 1.4.1, log source = /proc/kmsg started.
  4. Aug 4 13:50:15 holmes86 kernel: Linux version 2.6.22.1-8 (root@everestbuilder.linux-ren.org) (gcc version 4.2.0) #1 SMP Wed Jul 18 11:18:32 EDT 2007 Aug 4 13:50:15 holmes86 kernel: BIOS-provided physical RAM map: Aug 4 13:50:15 holmes86 kernel: BIOS-e820: 0000000000000000 - 000000000009f000 (usable) Aug 4 13:50:15 holmes86 kernel: BIOS-e820: 000000000009f000 - 00000000000a0000 (reserved) Aug 4 13:50:15 holmes86 kernel: BIOS-e820: 0000000000100000 - 000000001f7d3800 (usable) Aug 4 13:50:15 holmes86 kernel: BIOS-e820: 000000001f7d3800 - 0000000020000000 (reserved) Aug 4 13:50:15 holmes86 kernel: BIOS-e820: 00000000e0000000 - 00000000f0007000 (reserved) Aug 4 13:50:15 holmes86 kernel: BIOS-e820: 00000000f0008000 - 00000000f000c000 (reserved)
  5. 從上面的資訊可以看出,檢視 /proc/8663/fd/15 就可以得到所要恢復的資料。如果可以通過檔案描述符檢視相應的資料,那麼就可以使用 I/O 重定向將其複製到檔案中,如:
  6. cat /proc/1283/fd/2 > /var/log/messages

對於許多應用程式,尤其是日誌檔案和資料庫,這種恢復刪除檔案的方法非常有用。

使用命令
  1. lsof `which httpd` //那個程式在使用apache的可執行檔案
  2. lsof /etc/passwd //那個程式在佔用/etc/passwd
  3. lsof /dev/hda6 //那個程式在佔用hda6
  4. lsof /dev/cdrom //那個程式在佔用光碟機
  5. lsof -c sendmail //檢視sendmail程式的檔案使用情況
  6. lsof -c courier -u ^zahn //顯示出那些檔案被以courier打頭的程式開啟,但是並不屬於使用者zahn
  7. lsof -p 30297 //顯示那些檔案被pid為30297的程式開啟
  8. lsof -D /tmp 顯示所有在/tmp資料夾中開啟的instance和檔案的程式。但是symbol檔案並不在列
  9. lsof -u1000 //檢視uid是100的使用者的程式的檔案使用情況
  10. lsof -utony //檢視使用者tony的程式的檔案使用情況
  11. lsof -u^tony //檢視不是使用者tony的程式的檔案使用情況(^是取反的意思)
  12. lsof -i //顯示所有開啟的埠
  13. lsof -i:80 //顯示所有開啟80埠的程式
  14. lsof -i -U //顯示所有開啟的埠和UNIX domain檔案
  15. lsof -i UDP@[url]www.akadia.com:123 //顯示那些程式開啟了到www.akadia.com的UDP的123(ntp)埠的連結
  16. lsof -i tcp@ohaha.ks.edu.tw:ftp -r //不斷檢視目前ftp連線的情況(-r,lsof會永遠不斷的執行,直到收到中斷訊號,+r,lsof會一直執行,直到沒有檔案被顯示,預設是15s重新整理)
  17. lsof -i tcp@ohaha.ks.edu.tw:ftp -n //lsof -n 不將IP轉換為hostname,預設是不加上-n引數




來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/29733787/viewspace-2049149/,如需轉載,請註明出處,否則將追究法律責任。

相關文章