lsof 是 List Open File 的縮寫, 它主要用來獲取被進程打開文件的信息,我們都知道,在Linux中,一切皆文件,lsof命令可以查看所有已經打開了的文件,比如: 普通文件,目錄,特殊的塊文件,管道,socket套接字,設備,Unix域套接字等等。系統在后台都為該應用程序分配了一個文件描述符,無論這個文件的本質如何,該文件描述符為應用程序與基礎操作系統之間的交互提供了通用接口。同時,它還可以結合 grep 以及 ps 命令進行更多的高級搜索
lsof 命令可顯示系統打開的文件,因為 lsof 需要訪問核心內存和各種文件,所以必須以 root 用戶的身份運行它才能夠充分地發揮其功能。
1.命令格式
lsof [參數][文件]
2.命令功能
用於查看你進程開打的文件,打開文件的進程,進程打開的端口(TCP、UDP)。找回/恢復刪除的文件。是十分方便的系統監視工具,因為 lsof
需要訪問核心內存和各種文件,所以需要 root
用戶執行。
lsof
打開的文件可以是:
- 普通文件
- 目錄
- 網絡文件系統的文件
- 字符或設備文件
- (函數)共享庫
- 管道,命名管道
- 符號鏈接
- 網絡文件(例如:NFS file、網絡socket,unix域名socket)
- 還有其它類型的文件,等等
3.命令參數
[root@ito-yw-host ~]# lsof -h
lsof 4.87
latest revision: ftp://lsof.itap.purdue.edu/pub/tools/unix/lsof/
latest FAQ: ftp://lsof.itap.purdue.edu/pub/tools/unix/lsof/FAQ
latest man page: ftp://lsof.itap.purdue.edu/pub/tools/unix/lsof/lsof_man
usage: [-?abhKlnNoOPRtUvVX] [+|-c c] [+|-d s] [+D D] [+|-f[gG]] [+|-e s]
[-F [f]] [-g [s]] [-i [i]] [+|-L [l]] [+m [m]] [+|-M] [-o [o]] [-p s]
[+|-r [t]] [-s [p:s]] [-S [t]] [-T [t]] [-u s] [+|-w] [-x [fl]] [--] [names]
Defaults in parentheses; comma-separated set (s) items; dash-separated ranges.
-?|-h list help -a AND selections (OR) -b avoid kernel blocks
-c c cmd c ^c /c/[bix] +c w COMMAND width (9) +d s dir s files
-d s select by FD set +D D dir D tree *SLOW?* +|-e s exempt s *RISKY*
-i select IPv[46] files -K list tasKs (threads) -l list UID numbers
-n no host names -N select NFS files -o list file offset
-O no overhead *RISKY* -P no port names -R list paRent PID
-s list file size -t terse listing -T disable TCP/TPI info
-U select Unix socket -v list version info -V verbose search
+|-w Warnings (+) -X skip TCP&UDP* files -Z Z context [Z]
-- end option scan
+f|-f +filesystem or -file names +|-f[gG] flaGs
-F [f] select fields; -F? for help
+|-L [l] list (+) suppress (-) link counts < l (0 = all; default = 0)
+m [m] use|create mount supplement
+|-M portMap registration (-) -o o o 0t offset digits (8)
-p s exclude(^)|select PIDs -S [t] t second stat timeout (15)
-T qs TCP/TPI Q,St (s) info
-g [s] exclude(^)|select and print process group IDs
-i i select by IPv[46] address: [46][proto][@host|addr][:svc_list|port_list]
+|-r [t[m<fmt>]] repeat every t seconds (15); + until no files, - forever.
An optional suffix to t is m<fmt>; m must separate t from <fmt> and
<fmt> is an strftime(3) format for the marker line.
-s p:s exclude(^)|select protocol (p = TCP|UDP) states by name(s).
-u s exclude(^)|select login|UID set s
-x [fl] cross over +d|+D File systems or symbolic Links
names select named files or files on named file systems
Anyone can list all files; /dev warnings disabled; kernel ID check disabled.
-a
列出打開文件存在的進程-c
<進程名> 列出指定進程所打開的文件-g
列出GID號進程詳情-d
<文件號> 列出占用該文件號的進程+d
<目錄> 列出目錄下被打開的文件+D
<目錄> 遞歸列出目錄下被打開的文件-n
<目錄> 列出使用NFS的文件-i
<條件> 列出符合條件的進程。(4、6、協議、:端口、 @ip )-p
<進程號> 列出指定進程號所打開的文件-u
列出UID號進程詳情-h
顯示幫助信息-v
顯示版本信息
4.安裝
lsof 命令默認是沒有安裝的,而且它的使用需要有root權限或者賦予普通用於sudo權限, 使用以下命令安裝
yum install -y lsof
5.輸出解析
lsof 命令有很多可選參數,不帶任何參數執行 lsof 命令會輸出當前所有活躍進程打開的所有文件,由於lsof命令會輸出很多信息,在示例中我們查看前10行,對輸出字段進行解析
[root@centos-7.9 ~]# lsof | head
COMMAND PID TID USER FD TYPE DEVICE SIZE/OFF NODE NAME
systemd 1 root cwd DIR 253,0 4096 64 /
systemd 1 root rtd DIR 253,0 4096 64 /
systemd 1 root txt REG 253,0 1632736 67801506 /usr/lib/systemd/systemd
systemd 1 root mem REG 253,0 20064 33763358 /usr/lib64/libuuid.so.1.3.0
systemd 1 root mem REG 253,0 265576 34448764 /usr/lib64/libblkid.so.1.1.0
systemd 1 root mem REG 253,0 90248 33763451 /usr/lib64/libz.so.1.2.7
systemd 1 root mem REG 253,0 157424 33769169 /usr/lib64/liblzma.so.5.2.2
systemd 1 root mem REG 253,0 23968 33769162 /usr/lib64/libcap-ng.so.0.0.0
systemd 1 root mem REG 253,0 19896 33786740 /usr/lib64/libattr.so.1.1.0
輸出結果中列 COMMAND 、PID、TID、USER 分別表示進程名、進程ID、線程ID、所屬用戶
第一列中 systemd 的進程 ID 是 1,它是系統的守護進程
列 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 列表示路徑或者鏈接
6、實例
(1)列出指定用戶已打開的文件
使用 -u 選項可以列出指定用戶已經打開的文件,該選項后面可以接多個用戶名,每個用戶名之間用空格隔開,表示列出所有指定用戶已打開的所有文件
[root@centos-7.9 ~]# lsof -u gdm,apache
COMMAND PID USER FD TYPE DEVICE SIZE/OFF NODE NAME
php-fpm 1181 apache cwd DIR 253,0 4096 64 /
php-fpm 1181 apache rtd DIR 253,0 4096 64 /
php-fpm 1181 apache txt REG 253,0 4781848 103960545 /opt/rh/rh-php72/root/usr/sbin/php-fpm
php-fpm 1181 apache mem REG 253,0 70008 101418157 /usr/lib64/gconv/libGB.so
省略……
php-fpm 1181 apache 0u CHR 1,3 0t0 2052 /dev/null
php-fpm 1181 apache 1u CHR 1,3 0t0 2052 /dev/null
php-fpm 1181 apache 2u CHR 1,3 0t0 2052 /dev/null
php-fpm 1181 apache 9u unix 0xffff9fa3e5fa0880 0t0 12179700 /var/opt/rh/rh-php72/run/php-fpm/zabbix.sock
gnome-ses 2418 gdm cwd DIR 253,0 97 1444834 /var/lib/gdm
gnome-ses 2418 gdm rtd DIR 253,0 4096 64 /
gnome-ses 2418 gdm txt REG 253,0 298608 101780481 /usr/libexec/gnome-session-binary
省略……
上面的例子中,lsof -u gdm,apache
命令表示列出 dgm和apache 用戶已經打開了的文件
如果要排除指定用戶已經打開的文件,可以在用戶名前加 ^ 符號,下面的命令會列出除 apache 用戶外其他所有用戶已打開了的文件
lsof -u ^apache | more
(2)找出被刪除依然打開的文件
在一些場景中,你可能會發現磁盤空間滿了但找不到占用空間的文件,這很有可能是某些文件雖被刪除了,卻沒有釋放磁盤空間,這種情況往往是有進程打開了該文件。那我們如何找到這些刪除的文件呢?可以結合 grep 命令找出這種文件。lsof |grep deleted
可找出系統所有的被打開且已刪除的文件,你可以加上其他的選項以實現更精細查找,如查找mysql 用戶打開並刪除的文件 lsof -u mysql |grep deleted
。利用這種特性也可以實現刪除文件的恢復,
[root@centos-7.9 ~]# lsof |grep deleted
abrt-watc 1398 root 4r REG 253,0 32461 100937591 /var/log/Xorg.0.log (deleted)
rsyslogd 1872 root 8w REG 253,0 5028953 104140086 /var/log/cron-20210314 (deleted)
rs:main 1872 1924 root 8w REG 253,0 5028953 104140086 /var/log/cron-20210314 (deleted)
rs:main 1872 1924 root 9w REG 253,0 118985294 104140092 /var/log/maillog-20210314 (deleted)
X 2301 root 4w REG 253,0 32461 100937591 /var/log/Xorg.0.log (deleted)
llvmpipe- 2301 2361 root 4w REG 253,0 32461 100937591 /var/log/Xorg.0.log (deleted)
mysqld 2378 mysql 5u REG 253,0 0 67913255 /tmp/ibBmtyYs (deleted)
利用這種特性也可以實現刪除文件的恢復,打開 /var/log/cron-20210314 的進程 id 為1872 ,進入 /proc/1872/fd/ 就可以看到該進程打開的所有文件,已刪除的文件在末尾會標注 “(deleted)”,8 是指向/var/log/cron-20210314的,用head 查看下文件查到內容是完好的,現在就很容易恢復了。
[root@centos-7.9 ~]# cd /proc/1872/fd/
[root@centos-7.9 fd]# ll
總用量 0
lr-x------ 1 root root 64 3月 11 2021 0 -> /dev/null
lr-x------ 1 root root 64 3月 11 2021 3 -> anon_inode:inotify
l-wx------ 1 root root 64 3月 11 2021 4 -> /var/log/messages
省略……
l-wx------ 1 root root 64 3月 11 2021 8 -> /var/log/cron-20210314 (deleted)
l-wx------ 1 root root 64 3月 11 2021 9 -> /var/log/maillog-20210314 (deleted)
[root@centos-7.9 fd]# head 8
Mar 7 03:47:02 centos-7.9 run-parts(/etc/cron.daily)[11338]: finished logrotate
Mar 7 03:47:02 centos-7.9 run-parts(/etc/cron.daily)[11297]: starting man-db.cron
Mar 7 03:47:04 centos-7.9 run-parts(/etc/cron.daily)[11354]: finished man-db.cron
省略……
[root@centos-7.9 fd]#
(3)列出所有打開了的網絡文件
[root@centos-7.9 ~]# lsof -i |head -15
COMMAND PID USER FD TYPE DEVICE SIZE/OFF NODE NAME
rpcbind 1368 rpc 6u IPv4 13566 0t0 UDP *:sunrpc
rpcbind 1368 rpc 7u IPv4 13567 0t0 UDP *:connendp
rpcbind 1368 rpc 8u IPv4 13568 0t0 TCP *:sunrpc (LISTEN)
rpcbind 1368 rpc 9u IPv6 13569 0t0 UDP *:sunrpc
rpcbind 1368 rpc 10u IPv6 13570 0t0 UDP *:connendp
rpcbind 1368 rpc 11u IPv6 13571 0t0 TCP *:sunrpc (LISTEN)
avahi-dae 1373 avahi 12u IPv4 18700 0t0 UDP *:mdns
avahi-dae 1373 avahi 13u IPv4 18701 0t0 UDP *:52604
cupsd 1864 root 10u IPv6 121 0t0 TCP localhost:ipp (LISTEN)
cupsd 1864 root 11u IPv4 122 0t0 TCP localhost:ipp (LISTEN)
sshd 1866 root 3u IPv4 19927 0t0 TCP *:ssh (LISTEN)
sshd 1866 root 4u IPv6 19929 0t0 TCP *:ssh (LISTEN)
master 2217 root 13u IPv4 63727 0t0 TCP localhost:smtp (LISTEN)
master 2217 root 14u IPv6 63728 0t0 TCP localhost:smtp (LISTEN)
(4)列出所有 IPV4/6 網絡文件
列出所有已經打開了的 ipv4 網絡文件
[root@centos-7.9 ~]# lsof -i 4 |head
COMMAND PID USER FD TYPE DEVICE SIZE/OFF NODE NAME
rpcbind 1368 rpc 6u IPv4 13566 0t0 UDP *:sunrpc
rpcbind 1368 rpc 7u IPv4 13567 0t0 UDP *:connendp
rpcbind 1368 rpc 8u IPv4 13568 0t0 TCP *:sunrpc (LISTEN)
avahi-dae 1373 avahi 12u IPv4 18700 0t0 UDP *:mdns
avahi-dae 1373 avahi 13u IPv4 18701 0t0 UDP *:52604
cupsd 1864 root 11u IPv4 122 0t0 TCP localhost:ipp (LISTEN)
sshd 1866 root 3u IPv4 19927 0t0 TCP *:ssh (LISTEN)
master 2217 root 13u IPv4 63727 0t0 TCP localhost:smtp (LISTEN)
zabbix_ag 3802 zabbix 4u IPv4 70087 0t0 TCP *:zabbix-agent (LISTEN)
所有已經打開了的 ipv6 網絡文件
[root@centos-7.9 ~]# lsof -i 6 |head
COMMAND PID USER FD TYPE DEVICE SIZE/OFF NODE NAME
rpcbind 1368 rpc 9u IPv6 13569 0t0 UDP *:sunrpc
rpcbind 1368 rpc 10u IPv6 13570 0t0 UDP *:connendp
rpcbind 1368 rpc 11u IPv6 13571 0t0 TCP *:sunrpc (LISTEN)
cupsd 1864 root 10u IPv6 121 0t0 TCP localhost:ipp (LISTEN)
sshd 1866 root 4u IPv6 19929 0t0 TCP *:ssh (LISTEN)
master 2217 root 14u IPv6 63728 0t0 TCP localhost:smtp (LISTEN)
mysqld 2378 mysql 36u IPv6 39979 0t0 TCP *:mysql (LISTEN)
zabbix_ag 3802 zabbix 5u IPv6 70088 0t0 TCP *:zabbix-agent (LISTEN)
zabbix_ag 3804 zabbix 5u IPv6 70088 0t0 TCP *:zabbix-agent (LISTEN)
(5)列出在指定端口上打開的文件**
使用 lsof -i:端口號
可以獲得所有在指定端口號上打開的文件
[root@centos-7.9 ~]# lsof -i:22
COMMAND PID USER FD TYPE DEVICE SIZE/OFF NODE NAME
sshd 1866 root 3u IPv4 19927 0t0 TCP *:ssh (LISTEN)
sshd 1866 root 4u IPv6 19929 0t0 TCP *:ssh (LISTEN)
sshd 37696 root 3u IPv4 617315159 0t0 TCP centos-7.9:ssh->10.200.4.33:60638 (ESTABLISHED)
上面例子列出了所有在22號端口上打開的文件,包括IPv4/IPv6監聽和1個tcp連接
列出目前連接主機 localhost 上端口為:20,21,22,25,53,80相關的所有文件信息,且每隔3秒不斷的執行lsof指令
命令:
lsof -i @localhost:20,21,22,25,53,80 -r 3
(6)列出使用了指定協議(TCP/UDP) 的文件
使用 lsof -i TCP/UDP
列出使用了TCP 或 UDP 協議的文件
[root@centos-7.9 ~]# lsof -ni TCP
COMMAND PID USER FD TYPE DEVICE SIZE/OFF NODE NAME
rpcbind 1368 rpc 8u IPv4 13568 0t0 TCP *:sunrpc (LISTEN)
mysqld 2378 mysql 36u IPv6 39979 0t0 TCP *:mysql (LISTEN)
sshd 11956 root 3u IPv4 617470628 0t0 TCP 10.200.52.10:ssh->10.200.4.33:62917 (ESTABLISHED)
使用 lsof -i TCP:3306 列出使用了TCP 協議並且端口為3306的文件
[root@centos-7.9 ~]# lsof -ni TCP:2379
COMMAND PID USER FD TYPE DEVICE SIZE/OFF NODE NAME
coredns 18408 root 7u IPv4 247062628 0t0 TCP 192.168.10.201:39484->192.168.10.201:2379 (ESTABLISHED)
coredns 18408 root 8u IPv4 247149626 0t0 TCP 192.168.10.201:39486->192.168.10.201:2379 (ESTABLISHED)
coredns 18408 root 9u IPv4 247079604 0t0 TCP 192.168.10.201:39488->192.168.10.201:2379 (ESTABLISHED)
etcd 23441 etcd 6u IPv6 98156846 0t0 TCP *:2379 (LISTEN)
etcd 23441 etcd 11u IPv4 98156848 0t0 TCP 127.0.0.1:33226->127.0.0.1:2379 (ESTABLISHED)
etcd 23441 etcd 12u IPv6 98156849 0t0 TCP 127.0.0.1:2379->127.0.0.1:33226 (ESTABLISHED)
etcd 23441 etcd 13u IPv6 247086177 0t0 TCP 192.168.10.201:2379->192.168.10.201:39484 (ESTABLISHED)
etcd 23441 etcd 14u IPv6 247086178 0t0 TCP 192.168.10.201:2379->192.168.10.201:39486 (ESTABLISHED)
etcd 23441 etcd 15u IPv6 247086180 0t0 TCP 192.168.10.201:2379->192.168.10.201:39488 (ESTABLISHED)
使用 lsof -i TCP:1-1024
列出使用了TCP協議並且端口范圍為 1 到 1024 的文件
[root@centos-7.9 ~]# lsof -ni TCP:1-1024
列出誰在使用某個特定的udp端口,命令:
lsof -i udp:5500
Shell
或者:特定的tcp端口,命令:
lsof -i tcp:8081
(7)列出所有網絡文件系統
命令:
lsof -N
(8)列出在特定目錄打開的文件
lsof命令列出指定目錄中的所有打開文件
+D
選項會列出一個目錄和其子目錄中打開的文件
[root@centos-7.9 ~]# lsof +D /home/mysql/lib/mysql
COMMAND PID USER FD TYPE DEVICE SIZE/OFF NODE NAME
mysqld 2378 mysql cwd DIR 253,2 4096 268665313 /home/mysql/lib/mysql
mysqld 2378 mysql 3uW REG 253,2 50331648 268665315 /home/mysql/lib/mysql/ib_logfile0
mysqld 2378 mysql 4uW REG 253,2 18874368 268826238 /home/mysql/lib/mysql/zabbix/events.ibd
mysqld 2378 mysql 9uW REG 253,2 50331648 268665316 /home/mysql/lib/mysql/ib_logfile1
mysqld 2378 mysql 10uW REG 253,2 146800640 268665314 /home/mysql/lib/mysql/ibdata1
mysqld 2378 mysql 11uW REG 253,2 35001466880 268826226 /home/mysql/lib/mysql/zabbix/history_uint.ibd
略……
+d
選項只會列出當前目錄下已打開的文件
[root@centos-7.9 ~]# lsof +d /home/mysql/lib/mysql
COMMAND PID USER FD TYPE DEVICE SIZE/OFF NODE NAME
mysqld 2378 mysql cwd DIR 253,2 4096 268665313 /home/mysql/lib/mysql
mysqld 2378 mysql 3uW REG 253,2 50331648 268665315 /home/mysql/lib/mysql/ib_logfile0
mysqld 2378 mysql 9uW REG 253,2 50331648 268665316 /home/mysql/lib/mysql/ib_logfile1
mysqld 2378 mysql 10uW REG 253,2 146800640 268665314 /home/mysql/lib/mysql/ibdata1
mysqld 2378 mysql 19uW REG 253,2 79691776 268665280 /home/mysql/lib/mysql/ibtmp1
lsof 后也可以直接跟邏輯卷或磁盤
[root@centos-7.9 ~]# lsof /dev/mapper/centos-root
(9)列出指定進程ID打開的文件
進程ID是操作系統進程的唯一標識,如果想要知道某進程打開的文件可以使用 lsof -p PID
命令查詢
[root@centos-7.9 ~]# lsof -p 41927
COMMAND PID USER FD TYPE DEVICE SIZE/OFF NODE NAME
nginx 41927 root cwd DIR 253,0 4096 64 /
nginx 41927 root rtd DIR 253,0 4096 64 /
nginx 41927 root txt REG 253,0 1215088 34272922 /usr/sbin/nginx
nginx 41927 root mem REG 253,0 27624 2489009 /usr/lib64/perl5/vendor_perl/auto/nginx/nginx.so
nginx 41927 root 7u IPv6 179578988 0t0 TCP *:webcache (LISTEN)
nginx 41927 root 8u unix 0xffff9fb1486c6e80 0t0 179580272 socket
nginx 41927 root 9u unix 0xffff9fb1486c6a40 0t0 179580273 socket
nginx 41927 root 10u unix 0xffff9fb1486c61c0 0t0 179580274 socket
上述命令中,-p
選項后面可以指定多個進程ID,每個進程ID之間用逗號分隔,如果想排除掉某個進程打開的文件,可以在該進程ID前面加上 ^符號
lsof -p 1,2,3,^4
上述命令會列出進程1,進程2,進程3打開的所有文件,同時忽略進程4打開的文件
(10)列出某個程序進程所打開的文件信息
命令:
lsof -c mysql
Shell
說明:
-c
選項將會列出所有以mysql這個進程開頭的程序的文件,其實你也可以寫成 lsof | grep mysql, 但是第一種方法明顯比第二種方法要少打幾個字符了
列出多個進程多個打開的文件信息
命令:
lsof -c mysql -c apache
(11)據文件描述列出對應的文件信息
命令:
lsof -d description(like 2)
Shell
例如:lsof -d txt
例如:lsof -d 1
例如:lsof -d 2
說明:
0表示標准輸入,1表示標准輸出,2表示標准錯誤,從而可知:所以大多數應用程序所打開的文件的 FD 都是從 3 開始
根據文件描述范圍列出文件信息
命令:
lsof -d 2-3
Shell
列出COMMAND列中包含字符串”sshd”,且文件描符的類型為txt的文件信息
命令:
lsof -c sshd -a -d txt
(12)殺死特定條件的進程
在某些情況我們可能希望結束占用特定目錄的進程,可以結合kill命令使用,具體的命令如下
kill -9 `lsof -t -u zabbix`
kill -9 `lsof -t +D /home/mysql`
-t
選項之后表示結果只列出PID列,也就是進程ID列,其他列都忽略