Linux下 lsof 命令詳解



lsof 是 List Open File 的縮寫, 它主要用來獲取被進程打開文件的信息,我們都知道,在Linux中,一切皆文件,lsof命令可以查看所有已經打開了的文件,比如: 普通文件,目錄,特殊的塊文件,管道,socket套接字,設備,Unix域套接字等等,同時,它還可以結合 grep 以及 ps 命令進行更多的高級搜索

安裝

lsof 命令默認是沒有安裝的,而且它的使用需要有root權限或者賦予普通用於sudo權限, 使用以下命令安裝

yum install -y lsof

lsof 命令有很多可選參數,本文根據我自己的使用經驗整理了一些比較常用且重要的用法

列出所有打開的文件

不帶任何參數執行 lsof 命令會輸出當前所有活躍進程打開的所有文件

[root@ecs-centos-7 ~]# lsof | more
COMMAND     PID   TID    USER   FD      TYPE             DEVICE  SIZE/OFF       NODE NAME
systemd       1          root  cwd       DIR              253,1      4096          2 /
systemd       1          root  rtd       DIR              253,1      4096          2 /
systemd       1          root  txt       REG              253,1   1624520     530313 /usr/lib/systemd/systemd
systemd       1          root  mem       REG              253,1     20064     528340 /usr/lib64/libuuid.so.1.3.0
systemd       1          root  mem       REG              253,1    265600     532853 /usr/lib64/libblkid.so.1.1.0
systemd       1          root  mem       REG              253,1     90248     525942 /usr/lib64/libz.so.1.2.7
systemd       1          root  mem       REG              253,1    157424     525955 /usr/lib64/liblzma.so.5.2.2
systemd       1          root  mem       REG              253,1     23968     526159 /usr/lib64/libcap-ng.so.0.0.0
systemd       1          root  mem       REG              253,1     19896     526135 /usr/lib64/libattr.so.1.1.0
systemd       1          root  mem       REG              253,1     19288     525996 /usr/lib64/libdl-2.17.so
systemd       1          root  mem       REG              253,1    402384     525931 /usr/lib64/libpcre.so.1.2.0
systemd       1          root  mem       REG              253,1   2156160     

由於lsof命令會輸出很多信息,所以上面例子中使用了 lsof | more 來分頁顯示命令輸出結果

輸出結果中,第一列中 systemd 的進程ID是 1,它是一個守護進程

其中列 COMMANDPIDUSER 分別表示進程名、進程ID、所屬用戶

FD 是文件描述符,下面是可能的類型以及說明

FD 說明
cwd 當前目錄
txt txt文件
rtd root目錄
mem 內存映射文件

TYPE 是文件類型,下面是可能的值以及說明

TYPE 說明
DIR 目錄
REG 普通文件
CHR 字符
a_inode Inode文件
FIFO 管道或者socket文件
netlink 網絡
unknown 未知

DEVICE 表示設備ID

SIZE/OFF 表示進程大小

NODE 表示文件的Inode號

NAME 表示路徑或者鏈接

列出指定用戶已打開的文件

使用 -u 選項可以列出指定用戶已經打開的文件,該選項后面可以接多個用戶名,每個用戶名之間用空格隔開,表示列出所有指定用戶已打開的所有文件

[root@ecs-centos-7 ~]# lsof -u tt | more
COMMAND   PID USER   FD   TYPE DEVICE  SIZE/OFF   NODE NAME
bash    27789   tt  cwd    DIR  253,1      4096 131090 /home/tt
bash    27789   tt  rtd    DIR  253,1      4096      2 /
bash    27789   tt  txt    REG  253,1    964600 525779 /usr/bin/bash
vim     27813   tt  txt    REG  253,1   2337192 531847 /usr/bin/vim
vim     27813   tt    4u   REG  253,1     12288 131167 /home/tt/.p.txt.swp

上面的例子中,lsof -u tt 命令表示列出 tt 用戶已經打開了的文件,從結果可以看出,用戶打開了 /home/tt//usr/bin/bash/usr/bin/vim /home/tt/.p.txt.swp 這幾個文件

如果要排除指定用戶已經打開的文件,可以在用戶名前加 ^ 符號,下面的命令會列出除tt用戶外其他所有用戶已打開了的文件

lsof -u ^tt | more 

找出打開着但已被刪除了的文件

有這樣一種場景,有一個服務正在往日志文件中寫日志,這個時候,不小心把正在寫入的日志文件刪除了

上面的場景中,日志文件雖然被刪除了,但是文件仍然是打開着的,它仍然占用文件系統的空間,我們可以結合 grep 命令找出這種打開着,但是已經被刪除的文件

[root@ecs-centos-7 ~]# lsof -u tt | grep deleted
vim     27813   tt    4u   REG  253,1    12288 131167 /home/tt/.p.txt.swp(deleted)

上面例子中使用 lsof -u tt | grep deleted 命令查看用戶 tt打開着的確被刪除的文件

從結果可以看出,在往 p.txt寫入內容的時候,文件被刪除了

列出所有打開了的網絡文件

[root@ecs-centos-7 ~]# lsof -i
COMMAND    PID  USER   FD   TYPE DEVICE SIZE/OFF NODE NAME
ntpd       567   ntp   18u  IPv4  12657      0t0  UDP localhost:ntp
ntpd       567   ntp   22u  IPv6  16095      0t0  UDP ecs-centos-7.4-64bit-20200212:ntp 
dhclient   651  root    6u  IPv4  14594      0t0  UDP *:bootpc 
master     960  root   13u  IPv4  15791      0t0  TCP localhost:smtp (LISTEN)
master     960  root   14u  IPv6  15792      0t0  TCP localhost:smtp (LISTEN)
mysqld    1053 mysql   13u  IPv6  15147      0t0  TCP *:mysql (LISTEN)
sshd      1348  root    3u  IPv4  16698      0t0  TCP *:ssh (LISTEN)
  • 列出所有 IPV4/6 網絡文件

列出所有已經打開了的 ipv4 網絡文件

[root@ecs-centos-7 ~]# lsof -i 4
COMMAND    PID USER   FD   TYPE DEVICE SIZE/OFF NODE NAME
ntpd       567  ntp   16u  IPv4  12651      0t0  UDP *:ntp 
ntpd       567  ntp   18u  IPv4  12657      0t0  UDP localhost:ntp 
ntpd       567  ntp   21u  IPv4  16094      0t0  UDP ecs-centos-7.4-64bit-20200212:ntp 
dhclient   651 root    6u  IPv4  14594      0t0  UDP *:bootpc 
master     960 root   13u  IPv4  15791      0t0  TCP localhost:smtp (LISTEN)
sshd      1348 root    3u  IPv4  16698      0t0  TCP *:ssh (LISTEN)

所有已經打開了的 ipv6 網絡文件

[root@ecs-centos-7 ~]# lsof -i 6
COMMAND  PID  USER   FD   TYPE DEVICE SIZE/OFF NODE NAME
ntpd     567   ntp   17u  IPv6  12652      0t0  UDP *:ntp 
ntpd     567   ntp   19u  IPv6  12658      0t0  UDP localhost:ntp 
ntpd     567   ntp   22u  IPv6  16095      0t0  UDP ecs-centos-7.4-64bit-20200212:ntp 
master   960  root   14u  IPv6  15792      0t0  TCP localhost:smtp (LISTEN)
mysqld  1053 mysql   13u  IPv6  15147      0t0  TCP *:mysql (LISTEN)
sshd    1348  root    4u  IPv6  16700      0t0  TCP *:ssh (LISTEN)
  • 列出在指定端口上打開的文件

使用 lsof -i:端口號 可以獲得所有在指定端口號上打開的文件

[root@ecs-centos-7 ~]# lsof -i:22
COMMAND   PID USER   FD   TYPE DEVICE SIZE/OFF NODE NAME
sshd     1348 root    3u  IPv4  16698      0t0  TCP *:ssh (LISTEN)
sshd     1348 root    4u  IPv6  16700      0t0  TCP *:ssh (LISTEN)
sshd    27741 root    3u  IPv4 458958      0t0  TCP ecs-centos-7.4-64bit-20200212:ssh->113.118.121.220:42395 (ESTABLISHED)
sshd    27819 root    3u  IPv4 459250      0t0  TCP ecs-centos-7.4-64bit-20200212:ssh->113.118.121.220:19807 (ESTABLISHED)
sshd    27895 root    3u  IPv4 459828      0t0  TCP

上面例子列出了所有在22號端口上打開的文件

在服務器開發中,經常會部署一個網關或者代理程序,用來和客戶端通訊,網關或者代理程序需要開放一個固定的端口供客戶端連接用

如果客戶端連接不上網關或者代理程序,我們可以用上述命令檢查網關或代理程序的端口是否開啟,來排除因為端口關閉了導致連接不上網關的情況

  • 列出使用了指定協議(TCP/UDP) 的文件

使用 lsof -i TCP/UDP 列出使用了TCP 或 UDP 協議的文件

[root@cghost8 /home/cgyx]# lsof -i TCP | more
COMMAND      PID   USER   FD   TYPE  DEVICE SIZE/OFF NODE NAME
sshd        1704   root    3u  IPv4   13593      0t0  TCP *:ssh (LISTEN)
sshd        1704   root    4u  IPv6   13595      0t0  TCP *:ssh (LISTEN)
redis-serer   1725   root    4u  IPv4   19773      0t0  TCP localhost:6380 (LISTEN)
nc          2067   cgyx    4u  IPv4   39167      0t0  TCP *:60600 (LISTEN)
mysqld      3020  mysql    4u  IPv6 5514608      0t0  TCP 192.168.70.10:mysql->192.168.70.10:37084 (ESTABLISHED)

使用 lsof -i TCP:3306 列出使用了TCP 協議並且端口為3306的文件

[root@cghost8 /home/cgyx]# lsof -i TCP:3306
COMMAND      PID  USER   FD   TYPE  DEVICE SIZE/OFF NODE NAME
mysqld      3020 mysql    4u  IPv6 5514608      0t0  TCP 192.168.70.10:mysql->192.168.70.10:37084 (ESTABLISHED)

使用 lsof -i TCP:1-1024 列出使用了TCP協議並且端口范圍為 1 到 1024 的文件

[root@cghost8 /home/cgyx]# lsof -i TCP:1-1024
COMMAND   PID   USER   FD   TYPE  DEVICE SIZE/OFF NODE NAME
sshd     1704   root    3u  IPv4   13593      0t0  TCP *:ssh (LISTEN)
sshd     1704   root    4u  IPv6   13595      0t0  TCP *:ssh (LISTEN)
cupsd    1709   root   12u  IPv6   39148      0t0  TCP localhost:ipp (LISTEN)
cupsd    1709   root   13u  IPv4   39149      0t0  TCP localhost:ipp (LISTEN)
smbd     1824   root   35u  IPv6   17658      0t0  TCP *:microsoft-ds (LISTEN)
smbd     1824   root   36u  IPv6   17659      0t0  TCP *:netbios-ssn (LISTEN)
smbd     1824   root   37u  IPv4   17660      0t0  TCP *:microsoft-ds (LISTEN)
smbd     1824   root   38u  IPv4   17661      0t0  TCP *:netbios-ssn (LISTEN)

列出目錄中所有打開的文件

可以使用lsof命令列出指定目錄中的所有打開文件

現有一個data目錄 ,結構如下:

[root@ecs-centos-7 tt]# tree data/
data/
├── dira
│   └── a.txt
└── d.s

1 directory, 2 files

列出 data 目錄中打開的文件

[root@ecs-centos-7 tt]# lsof +D ./data/
COMMAND   PID USER   FD   TYPE DEVICE SIZE/OFF   NODE NAME
bash    28473 root  cwd    DIR  253,1     4096 131146 ./data
bash    28502 root  cwd    DIR  253,1     4096 131172 ./data/dira
vim     28530 root  cwd    DIR  253,1     4096 131172 ./data/dira
vim     28530 root    4u   REG  253,1    12288 131174 ./data/dira/.a.txt.swp

[root@ecs-centos-7 tt]# lsof +d ./data/
COMMAND   PID USER   FD   TYPE DEVICE SIZE/OFF   NODE NAME
bash    28473 root  cwd    DIR  253,1     4096 131146 ./data
bash    28502 root  cwd    DIR  253,1     4096 131172 ./data/dira
vim     28530 root  cwd    DIR  253,1     4096 131172 ./data/dira

上面例子中,+D+d 選項都是列出目錄中打開的文件

+D 選項會列出一個目錄和其子目錄中打開的文件,而 +d 選項只會列出當前目錄下已打開的文件

列出指定進程ID打開的文件

進程ID是操作系統進程的唯一標識,以下命令列出了進程ID為 1053 相關的文件, 從結果中可以知道這個進程ID對應的進程是MySQL

[root@ecs-centos-7 ~]# lsof -p 1053
COMMAND  PID  USER   FD   TYPE             DEVICE  SIZE/OFF    NODE NAME
mysqld  1053 mysql  cwd    DIR              253,1      4096 1055765 /var/lib/mysql
mysqld  1053 mysql  rtd    DIR              253,1      4096       2 /
mysqld  1053 mysql  txt    REG              253,1 251841448  534935 /usr/sbin/mysqld
mysqld  1053 mysql  mem    REG              253,1    209512  659436 /usr/lib64/mysql/plugin/validate_password.so
mysqld  1053 mysql    1w   REG              253,1    206658  924771 /var/log/mysqld.log
mysqld  1053 mysql    2w   REG              253,1    206658  924771 /var/log/mysqld.log

上述命令中,-p 選項后面可以指定多個進程ID,每個進程ID之間用逗號分隔,如果想排除掉某個進程打開的文件,可以在該進程ID前面加上 ^符號

lsof -p 1,2,3,^4

上述命令會列出進程1,進程2,進程3打開的所有文件,同時忽略進程4打開的文件

殺死指定用戶的所有進程

前面介紹了列出指定用戶所有打開的文件,我們可以組合 kill 命令一起使用,實現殺死指定用戶的所有進程的功能,具體的命令如下

kill -9 `lsof -t -u tt`

上述命令中,lsof -u tt 是列出tt用戶所有打開的文件,加上 -t 選項之后表示結果只列出PID列,也就是進程ID列,其他列都忽略,前面的 kill -9 表示強制結束指定的進程ID

小結

本文介紹了 lsof 命令的一些常見用法,它還有很多其他的用法,請自行查看man文檔


免責聲明!

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



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