藍(lán)隊(duì)云小課堂:
lsof 是 List Open File 的縮寫, 它主要用來獲取被進(jìn)程打開文件的信息,我們都知道,在Linux中,一切皆文件,lsof命令可以查看所有已經(jīng)打開了的文件,比如: 普通文件,目錄,特殊的塊文件,管道,socket套接字,設(shè)備,Unix域套接字等等,同時(shí),它還可以結(jié)合 grep 以及 ps 命令進(jìn)行更多的高級(jí)搜索
安裝
lsof 命令默認(rèn)是沒有安裝的,而且它的使用需要有root權(quán)限或者賦予普通用于sudo權(quán)限, 使用以下命令安裝
yum install -y lsof
lsof 命令有很多可選參數(shù),本文根據(jù)我自己的使用經(jīng)驗(yàn)整理了一些比較常用且重要的用法
列出所有打開的文件
不帶任何參數(shù)執(zhí)行 lsof 命令會(huì)輸出當(dāng)前所有活躍進(jìn)程打開的所有文件
[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命令會(huì)輸出很多信息,所以上面例子中使用了 lsof | more 來分頁(yè)顯示命令輸出結(jié)果
輸出結(jié)果中,第一列中 systemd 的進(jìn)程ID是 1,它是一個(gè)守護(hù)進(jìn)程
其中列 COMMAND 、PID、USER 分別表示進(jìn)程名、進(jìn)程ID、所屬用戶
列 FD 是文件描述符,下面是可能的類型以及說明
FD | 說明 |
cwd | 當(dāng)前目錄 |
txt | txt文件 |
rtd | root目錄 |
mem | 內(nèi)存映射文件 |
列 TYPE 是文件類型,下面是可能的值以及說明
TYPE | 說明 |
DIR | 目錄 |
REG | 普通文件 |
CHR | 字符 |
a_inode | Inode文件 |
FIFO | 管道或者socket文件 |
netlink | 網(wǎng)絡(luò) |
unknown | 未知 |
列 DEVICE 表示設(shè)備ID
列 SIZE/OFF 表示進(jìn)程大小
列 NODE 表示文件的Inode號(hào)
列NAME 表示路徑或者鏈接
列出指定用戶已打開的文件
使用 -u 選項(xiàng)可以列出指定用戶已經(jīng)打開的文件,該選項(xiàng)后面可以接多個(gè)用戶名,每個(gè)用戶名之間用空格隔開,表示列出所有指定用戶已打開的所有文件
[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 用戶已經(jīng)打開了的文件,從結(jié)果可以看出,用戶打開了 /home/tt、/、/usr/bin/bash、/usr/bin/vim、/home/tt/.p.txt.swp 這幾個(gè)文件
如果要排除指定用戶已經(jīng)打開的文件,可以在用戶名前加 ^ 符號(hào),下面的命令會(huì)列出除tt用戶外其他所有用戶已打開了的文件
lsof -u ^tt | more
找出打開著但已被刪除了的文件
有這樣一種場(chǎng)景,有一個(gè)服務(wù)正在往日志文件中寫日志,這個(gè)時(shí)候,不小心把正在寫入的日志文件刪除了
上面的場(chǎng)景中,日志文件雖然被刪除了,但是文件仍然是打開著的,它仍然占用文件系統(tǒng)的空間,我們可以結(jié)合 grep 命令找出這種打開著,但是已經(jīng)被刪除的文件
[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打開著的確被刪除的文件
從結(jié)果可以看出,在往 p.txt寫入內(nèi)容的時(shí)候,文件被刪除了
列出所有打開了的網(wǎng)絡(luò)文件
[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)
列出所有已經(jīng)打開了的 ipv4 網(wǎng)絡(luò)文件
[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)
所有已經(jīng)打開了的 ipv6 網(wǎng)絡(luò)文件
[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:端口號(hào) 可以獲得所有在指定端口號(hào)上打開的文件
[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號(hào)端口上打開的文件
在服務(wù)器開發(fā)中,經(jīng)常會(huì)部署一個(gè)網(wǎng)關(guān)或者代理程序,用來和客戶端通訊,網(wǎng)關(guān)或者代理程序需要開放一個(gè)固定的端口供客戶端連接用
如果客戶端連接不上網(wǎng)關(guān)或者代理程序,我們可以用上述命令檢查網(wǎng)關(guān)或代理程序的端口是否開啟,來排除因?yàn)槎丝陉P(guān)閉了導(dǎo)致連接不上網(wǎng)關(guān)的情況
使用 lsof -i TCP/UDP 列出使用了TCP 或 UDP 協(xié)議的文件
[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 協(xié)議并且端口為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協(xié)議并且端口范圍為 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命令列出指定目錄中的所有打開文件
現(xiàn)有一個(gè)data目錄 ,結(jié)構(gòu)如下:
[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 選項(xiàng)都是列出目錄中打開的文件
+D 選項(xiàng)會(huì)列出一個(gè)目錄和其子目錄中打開的文件,而 +d 選項(xiàng)只會(huì)列出當(dāng)前目錄下已打開的文件
列出指定進(jìn)程ID打開的文件
進(jìn)程ID是操作系統(tǒng)進(jìn)程的唯一標(biāo)識(shí),以下命令列出了進(jìn)程ID為 1053 相關(guān)的文件, 從結(jié)果中可以知道這個(gè)進(jìn)程ID對(duì)應(yīng)的進(jìn)程是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 選項(xiàng)后面可以指定多個(gè)進(jìn)程ID,每個(gè)進(jìn)程ID之間用逗號(hào)分隔,如果想排除掉某個(gè)進(jìn)程打開的文件,可以在該進(jìn)程ID前面加上 ^符號(hào)
lsof -p 1,2,3,^4
上述命令會(huì)列出進(jìn)程1,進(jìn)程2,進(jìn)程3打開的所有文件,同時(shí)忽略進(jìn)程4打開的文件
殺死指定用戶的所有進(jìn)程
前面介紹了列出指定用戶所有打開的文件,我們可以組合 kill 命令一起使用,實(shí)現(xiàn)殺死指定用戶的所有進(jìn)程的功能,具體的命令如下
kill -9 `lsof -t -u tt`
上述命令中,lsof -u tt 是列出tt用戶所有打開的文件,加上 -t 選項(xiàng)之后表示結(jié)果只列出PID列,也就是進(jìn)程ID列,其他列都忽略,前面的 kill -9 表示強(qiáng)制結(jié)束指定的進(jìn)程ID
更多小知識(shí),可聯(lián)系藍(lán)隊(duì)云一起探討。