lsof 是 List Open File 的縮寫, 它主要用來獲取被程序開啟檔案的資訊,我們都知道,在Linux中,一切皆檔案,lsof命令可以檢視所有已經打開了的檔案,比如: 普通檔案,目錄,特殊的塊檔案,管道,socket套接字,裝置,Unix域套接字等等,同時,它還可以結合 grep 以及 ps 命令進行更多的高階搜尋
安裝
lsof 命令預設是沒有安裝的,而且它的使用需要有root許可權或者賦予普通用於sudo許可權, 使用以下命令安裝
yum install -y lsof
lsof 命令有很多可選引數,本文根據我自己的使用經驗整理了一些比較常用且重要的用法
列出所有開啟的檔案
不帶任何引數執行 lsof 命令會輸出當前所有活躍程序開啟的所有檔案
[root@ecs-centos-7 ~]# lsof | moreCOMMAND PID TID USER FD TYPE DEVICE SIZE/OFF NODE NAMEsystemd 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/systemdsystemd 1 root mem REG 253,1 20064 528340 /usr/lib64/libuuid。so。1。3。0systemd 1 root mem REG 253,1 265600 532853 /usr/lib64/libblkid。so。1。1。0systemd 1 root mem REG 253,1 90248 525942 /usr/lib64/libz。so。1。2。7systemd 1 root mem REG 253,1 157424 525955 /usr/lib64/liblzma。so。5。2。2systemd 1 root mem REG 253,1 23968 526159 /usr/lib64/libcap-ng。so。0。0。0systemd 1 root mem REG 253,1 19896 526135 /usr/lib64/libattr。so。1。1。0systemd 1 root mem REG 253,1 19288 525996 /usr/lib64/libdl-2。17。sosystemd 1 root mem REG 253,1 402384 525931 /usr/lib64/libpcre。so。1。2。0systemd 1 root mem REG 253,1 2156160
由於lsof命令會輸出很多資訊,所以上面例子中使用了 lsof | more 來分頁顯示命令輸出結果
輸出結果中,第一列中 systemd 的程序ID是 1,它是一個守護程序
其中列 COMMAND 、PID、USER 分別表示程序名、程序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 | moreCOMMAND PID USER FD TYPE DEVICE SIZE/OFF NODE NAMEbash 27789 tt cwd DIR 253,1 4096 131090 /home/ttbash 27789 tt rtd DIR 253,1 4096 2 /bash 27789 tt txt REG 253,1 964600 525779 /usr/bin/bashvim 27813 tt txt REG 253,1 2337192 531847 /usr/bin/vimvim 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 deletedvim 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 -iCOMMAND PID USER FD TYPE DEVICE SIZE/OFF NODE NAMEntpd 567 ntp 18u IPv4 12657 0t0 UDP localhost:ntpntpd 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 4COMMAND PID USER FD TYPE DEVICE SIZE/OFF NODE NAMEntpd 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 6COMMAND PID USER FD TYPE DEVICE SIZE/OFF NODE NAMEntpd 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:22COMMAND PID USER FD TYPE DEVICE SIZE/OFF NODE NAMEsshd 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 | moreCOMMAND PID USER FD TYPE DEVICE SIZE/OFF NODE NAMEsshd 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:3306COMMAND PID USER FD TYPE DEVICE SIZE/OFF NODE NAMEmysqld 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-1024COMMAND PID USER FD TYPE DEVICE SIZE/OFF NODE NAMEsshd 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。s1 directory, 2 files
列出 data 目錄中開啟的檔案
[root@ecs-centos-7 tt]# lsof +D 。/data/COMMAND PID USER FD TYPE DEVICE SIZE/OFF NODE NAMEbash 28473 root cwd DIR 253,1 4096 131146 。/databash 28502 root cwd DIR 253,1 4096 131172 。/data/diravim 28530 root cwd DIR 253,1 4096 131172 。/data/diravim 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 NAMEbash 28473 root cwd DIR 253,1 4096 131146 。/databash 28502 root cwd DIR 253,1 4096 131172 。/data/diravim 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 1053COMMAND PID USER FD TYPE DEVICE SIZE/OFF NODE NAMEmysqld 1053 mysql cwd DIR 253,1 4096 1055765 /var/lib/mysqlmysqld 1053 mysql rtd DIR 253,1 4096 2 /mysqld 1053 mysql txt REG 253,1 251841448 534935 /usr/sbin/mysqldmysqld 1053 mysql mem REG 253,1 209512 659436 /usr/lib64/mysql/plugin/validate_password。somysqld 1053 mysql 1w REG 253,1 206658 924771 /var/log/mysqld。logmysqld 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文件