Linux lsof工具介紹


引言

Linux fuser工具介紹》一文中,與大家一起學習了fuser工具的使用方法。"lsof"——list open fileslsof也是Linux下用於查看打開的文件以及相關聯進程信息的工具,相比fuser提供更強大的功能,下面我們就來學習lsof的使用方法。

 

lsof輸出說明

直接執行lsof,將輸出系統中所有打開文件的信息,這里說的文件不單指一般的文件,還包括目錄、socket套接字、設備文件和命名管道:

#lsof
COMMAND     PID       USER   FD      TYPE             DEVICE SIZE/OFF       NODE NAME
init          1       root  cwd       DIR                8,2     4096          2 /
init          1       root  rtd       DIR                8,2     4096          2 /
init          1       root  txt       REG                8,2    40784    6488145 /sbin/init
init          1       root  mem       REG                8,2    19114    3874831 /lib64/libdl-2.11.1.so
init          1       root   10u     FIFO               0,15      0t0       2677 /dev/initctl
……

每行顯示一個打開的文件,各列含義如下:

  • COMMAND:與文件關聯進程的名稱
  • PID:進程PID
  • USER:拉起進程的用戶
  • FD:指示進程與文件的關聯關系
  • TYPE:指示文件類型
  • DEVICE:指示文件所在設備的設備號(major,minor)
  • SIZE/OFF:指示文件的大小或進程對文件操作的偏移量
  • NODE:文件索引標識
  • NAME:文件名

FD列值的含義與fuser查詢結果中PID后接字符的含義相同,指示了進程與文件的關聯關系,有以下常見取值:

  • cwd:進程工作目錄
  • txt:進程由該文件拉起(如二進制文件或腳本)
  • rtd:進程的根目錄
  • mem:內存映射文件
  • N(u/w/r):指示該文件為進程打開的第N個文件描述符,u為可讀可寫模式,w為可寫模式,r為可讀模式

TYPE列有以下常見取值:

  • REG:一般文件
  • DIR:目錄
  • CHR:字符設備
  • BLK:塊設備
  • FIFO:命名管道
  • PIPE:管道
  • IPV4:ipv4套接字
  • unix:unix域套接字

根據以上字段,我們就可以了解到哪個文件以何種關聯方式與哪個進程關聯。但單執行lsof輸出太多,為獲取必要輸出,我們就得加一些過濾選項。

 

查詢某個進程打開的文件

lsof常見的用法是查找進程打開的文件名稱和文件數目,以下我們使用lsof查看pid14586syslog-ng進程使用了哪些文件:

# lsof -p 14586
COMMAND     PID USER   FD   TYPE             DEVICE SIZE/OFF    NODE NAME
syslog-ng 14586 root  cwd    DIR                8,2     4096       2 /
syslog-ng 14586 root  rtd    DIR                8,2     4096       2 /
syslog-ng 14586 root  txt    REG                8,2   386456 6488333 /sbin/syslog-ng
syslog-ng 14586 root  mem    REG                8,2    61467 3874842 /lib64/libnss_files-2.11.1.so
syslog-ng 14586 root    0r   CHR                1,3      0t0    2707 /dev/null
syslog-ng 14586 root    1w   CHR                1,3      0t0    2707 /dev/null
syslog-ng 14586 root    2w   CHR                1,3      0t0    2707 /dev/null
syslog-ng 14586 root    3u  unix 0xffff8804787d59c0      0t0   23639 /var/lib/dhcp/dev/log
syslog-ng 14586 root    4u  unix 0xffff880475db46c0      0t0   23641 /dev/log
syslog-ng 14586 root    5w   REG                8,2  2268859 5858016 /var/log/messages

從以上查詢結果可知,syslog-ng進程由/sbin/syslog-ng拉起,進程根目錄和當前工作目錄均為系統根目錄,進程的標准輸出、標准輸入和標准出錯輸出均被重定向至/dev/null/var/log/messagessyslog-ng以可寫模式打開。

 

Linux限制了進程能夠打開文件的數目,通過如下命令可以查看該限制:

# ulimit -n
1024

 

若進程打開文件句柄的數目超過系統限制,則相應進程不能正常服務,使用如下方式我們可以查看各個進程打開文件句柄的數目:

# lsof -n|awk '{print $2}'|sort|uniq -c|sort -nr| more

 

查詢某個文件被哪些進程打開

lsof命令后直接接文件名,可以查到該文件被哪些進程打開:

# lsof /var/log/messages
COMMAND     PID USER   FD   TYPE DEVICE SIZE/OFF    NODE NAME
syslog-ng 14586 root    5w   REG    8,2  2326134 5858016 /var/log/messages

要刪除文件時要先中止進程,而不是直接刪除這個文件。

 

umount文件系統時,如果文件系統中有打開的文件,那么umount操作會失敗,報“device is busy”。這時可使用”lsof /dev/sdaX”顯示sdaX文件系統中被打開的所有文件,再關閉所列文件。

 

進程的當前工作目錄影響文件系統的卸載,這也是為什么在編寫后台進程時需要將其工作目錄設置為根目錄的原因,

 

恢復刪除文件

最后,來介紹使用lsof命令恢復被刪文件的用法:某文件被刪除,但從lsof能查到該文件仍被某進程打開,這時我們可以恢復被刪文件。以下通過一個小程序說明該用法:

#include <unistd.h>
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>

int main(int argc, char** argv)
{
        int fd;
        char buf[10];
        fd = open("test.txt", O_RDONLY);
        read(fd, buf, 10);
        while(1)
        {
                sleep(2);
                printf("%s", buf);
        }
        return 0;
}

 

以上程序打開test.txt文件並定時輸出該文件內容,在編譯、拉起該程序之后,我們將test.txt文件刪除,之后使用lsof查到打開該文件的進程:

# lsof | grep test.txt
ttt       12347       root    3r      REG                8,2        6    2334724 /tmp/lx/test.txt (deleted)

 

接着,在/proc中可以看到該進程打開的文件描述符如下:

# ll /proc/12347/fd
total 0
lrwx------ 1 root root 64 May  2 11:43 0 -> /dev/pts/1
lrwx------ 1 root root 64 May  2 11:43 1 -> /dev/pts/1
lrwx------ 1 root root 64 May  2 11:43 2 -> /dev/pts/1
lr-x------ 1 root root 64 May  2 11:43 3 -> /tmp/lx/test.txt (deleted)

 

執行以下命令我們即可將/tmp/lx/test.txt文件的內容恢復至/tmp/test.txt

# cat /proc/12347/fd/3 > /tmp/test.txt

 

當進程打開了某個文件時,只要該進程保持打開該文件,即使將文件刪除,文件依然存在於磁盤中。進程並不知道文件已經被刪除,它依然可以使用打開該文件時獲取到的文件描述符進行讀取和寫入。除了該進程外,這個文件是不可見的,因為已經刪除了其相應的目錄條目。

 

小結

本文介紹了lsof的使用方法,包括lsof命令的輸出格式,如何根據某進程查詢其打開的文件,又如何查詢某文件被哪些進程打開,以及判斷進程打開文件數是否達到上限的方法、刪除文件/卸載文件系統時需注意的事項,最后介紹了使用lsof恢復被刪除文件的方法。

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM