您当前的位置: 首页 >  liaowenxiong linux

Linux 命令之 lsof -- 列出当前系统已打开的文件列表

liaowenxiong 发布时间:2021-04-22 17:05:27 ,浏览量:3

文章目录

  • 命令介绍
  • 常用选项
  • 字段说明
  • 文件类型
  • 文件描述符
  • 文件状态模式
  • 锁模式
  • 参考示例
    • (一)查看打开指定文件的所有进程
    • (二)列出由某个 PID 对应的进程打开的所有文件
    • (三)查看指定名称的进程所打开的文件列表
    • (四)列出除了某个用户以外的被打开的文件列表
    • (五)列出除了某个进程之外,其它进程打开的文件列表
    • (六)列出所有的网络连接
    • (七)列出所有的 TCP 网络连接
    • (八)列出所有的 UDP 网络连接
    • (九)查看有哪些进程在使用指定的端口
    • (十)查看哪些进程在使用指定的 UDP 端口
    • (十一)查看哪些进程在使用指定的 TCP 端口
    • (十二)列出某个用户所有活跃的网络端口
    • (十三)查看指定用户组所打开的文件列表
    • (十四)根据文件描述符的范围查看有关的文件列表
    • (十五)哪些进程在使用 apache 的可执行文件
    • (十六)查看连接到某个远程主机端口的进程
    • (十七)不断查看远程主机 ftp 连接的情况
    • (十八)递归查找某个目录中所有打开的文件
    • (十九)列出某个用户打开的所有文件
    • (二十)列出由某个用户或某个进程打开的所有文件
    • (二十一)查看某个用户的所有网络连接
    • (二十二)列出所有内存映射文件
    • (二十三)列出所有加载在内存中并正在执行的进程
    • (二十四)查看使用网络资源的进程 pid
    • (二十五)杀掉所有使用网络的进程
    • (二十六)循环列出文件
    • (二十七)查看被打开的和网络相关的文件
    • (二十八)统计系统打开的文件总数
    • (二十九)杀掉属于某个用户的打开了文件的所有进程
    • (三十)列出某个 IP 的网络连接信息
    • (三十一)同时列出连接某主机多个端口的网络连接文件
  • 经典场景应用
    • (一)查看指定进程打开的特定文件(查看日志文件路径)
    • (二)查看文件的内存映射路径(查看已删除文件的内容)
    • (三)恢复被删除的文件
    • (四) 日志文件删除后磁盘空间可用空间没有变大,怎么解决

命令介绍

lsofList Opened Files 的缩写,该命令是用于列出当前系统打开的文件的工具,也就是查看被进程打开的文件的工具,且可以用来找回或恢复被删除的文件。

在 Linux 下“一切皆文件”,任何事物都以文件的形式存在,包括但不限于 pipes, sockets, directories, devices等。通过文件不仅仅可以访问常规数据,还可以访问网络连接和硬件,例如:传输控制协议 (TCP) 和用户数据报协议 (UDP) 套接字等。

lsof 是一个 Linux 下的非常实用和方便的系统级的监控、诊断工具。因为 lsof 命令需要访问核心内存和各种文件,所以必须以 root 用户的身份运行它才能够充分地发挥其功能。

系统在后台为每个应用程序分配了一个文件描述符(程序打开文件,系统都会分配一个文件描述符给该程序),该文件描述符为应用程序与基础操作系统之间的交互提供了通用接口。因为应用程序打开文件的描述符列表提供了大量关于这个应用程序本身的信息,因此通过 lsof 工具查看这个列表,对系统监测以及排错将是很有帮助的。

lsof 显示的结果中,每行显示一个打开的文件,若不指定条件默认显示所有进程打开的所有文件。

常用选项

选项说明
-a指示多个选项之间为 的关系,必须都满足时才显示结果
-c列出指定进程所打开的文件
-g显示归属于 GID 的进程情况
-d列出占用该文件号的进程,文件号就是文件描述符。例如:显示使用fd为4的进程
+d列出指定目录下被打开的文件
+D递归列出指定目录下被打开的文件
-n列出使用NFS的文件
-n不解析主机名 ,不将 IP 转换为 Host Name,缺省是不加上 -n 选项,疑问??
-i列出符合条件的且与网络相关的进程。(4、6、协议、:端口、 @ip )不加条件默认列出所有的网络连接。
-p列出指定进程号所打开的文件
-P不解析端口号
-N列出所有NFS(网络文件系统)文件
-u列出指定用户打开的文件, 该选项可以指定用户名 或 user ID,可以通过逗号分隔多个用户名称或 user ID,也可以通过符号 ^ 对条件取反
-U列出所有UNIX域Socket文件
-t只输出 PID
-h显示帮助信息
-v显示版本信息

字段说明

字段名称说明
COMMAND进程的名称,默认以 9 个字符长度显示的命令名称。可使用 +c 参数指定显示的宽度,若 +c 后跟的参数为零,则显示命令的全名。这个 +c 参数好像无效
PID进程标识符
PPID父进程标识符,父进程的IP号,默认不显示,当使用 -R 参数可打开。
USER进程所有者,命令的执行 UID 或系统中登陆的用户名称。默认显示为用户名,当使用 -l 参数时,可显示 UID。
PGID进程所属组标识符,进程组的ID 编号,默认也不会显示,当使用 -g 参数时可打开。
FDFile Descriptor Number,文件描述符,应用程序通过文件描述符识别文件,例如:cwd、txt 等
TYPE文件类型,例如: DIR、REG 等
DEVICE指定磁盘的名称,以逗号分隔设备编号,使用character special、block special表示的设备号
SIZE文件的大小,如果不能用大小表示的,会留空。使用-s参数控制。
NODE索引节点(文件在磁盘上的标识),本地文件的node码,或者协议,如TCP等
NAME打开文件的确切名称,挂载点和文件的全路径(链接会被解析为实际路径),或者连接双方的地址和端口、状态等

文件类型

英文标识说明
REG普通文件
DIR表示目录
CHR表示字符类型
BLK块设备类型
UNIXUNIX 域套接字,UNIX Domain Sockets
FIFO先进先出 (FIFO) 队列
IPv4/IPv6网际协议 (IP) 套接字,IPv4/IPv6 套接字
LINK链接文件

文件描述符

描述符说明
cwdCurrent Work Director 的缩写,应用程序的当前工作目录,这是该应用程序启动的目录,除非它本身对这个目录进行更改
txt该类型的文件是程序代码,表示程序的可执行文件
lnnlibrary references (AIX)
erFD information error (see NAME column)
jldjail directory (FreeBSD)
ltxshared library text (code and data)
mxxhex memory-mapped type number xx
m86DOS Merge mapped file
memmemory-mapped file,表示内存映射文件
mmapmemory-mapped device
pdparent directory
rtdroot directory,表示根目录
trkernel trace file (OpenBSD)
v86VP/ix mapped file
0表示标准输出
1表示标准输入
2表示标准错误

文件状态模式

一般在标准输出、标准错误、标准输入后还跟着文件状态模式。

文件状态模式说明
u表示该文件被打开并处于读取/写入模式,例如:10u,10 是打开该文件时返回的一个整数,表示文件号是10,u 表示该文件被打开且处于读取/写入模式
r表示该文件被打开并处于只读模式
w表示该文件被打开并处于只写模式
space表示该文件的状态模式为 unknow,且没有锁定
-表示该文件的状态模式为 unknow,且被锁定

锁模式

在文件状态模式后面,还跟着相关的锁:

锁模式说明
Nfor a Solaris NFS lock of unknown type
rfor read lock on part of the file
Rfor a read lock on the entire file
wfor a write lock on part of the file(文件的部分写锁)
Wfor a write lock on the entire file(整个文件的写锁)。表示该应用程序拥有对整个文件的写锁(表示该进程拥有对文件写操作的锁),该文件描述符用于确保每次只能打开一个应用程序实例。初始打开每个应用程序时,都具有三个文件描述符,从 0 到 2,分别表示标准输入、标准输出和标准错误。所以大多数应用程序所打开的文件的 FD 都是从 3 开始。
ufor a read and write lock of any length
Ufor a lock of unknown type
xfor an SCO OpenServer Xenix lock on part of the file
Xfor an SCO OpenServer Xenix lock on the entire file
spaceif there is no lock。表示该文件的状态模式为 unknow,且没有锁定。
-表示该文件的状态模式为 unknow,且被锁定。

参考示例

(一)查看打开指定文件的所有进程

  1. 查看哪些进程正在使用文件 /var/log/mysqld.log
[root@htlwk0001host ~]# lsof /var/log/mysqld.log
COMMAND     PID  USER   FD   TYPE DEVICE SIZE/OFF   NODE NAME
mysqld  1064381 mysql    1w   REG  253,1  3240699 935706 /var/log/mysqld.log
mysqld  1064381 mysql    2w   REG  253,1  3240699 935706 /var/log/mysqld.log
  1. 哪些进程在占用文件 /etc/passwd
[root@htlwk0001host ~]# lsof /etc/passwd
  1. 哪些进程在占用 hda6:
[root@htlwk0001host ~]# lsof /dev/hda6 
  1. 哪些进程在占用光驱:
[root@htlwk0001host ~]# lsof /dev/cdrom 

(二)列出由某个 PID 对应的进程打开的所有文件

查看 PID 为 1064381 的进程所打开的全部文件列表:

[root@htlwk0001host ~]# lsof -p 1064381
COMMAND     PID  USER   FD   TYPE             DEVICE  SIZE/OFF      NODE NAME
mysqld  1064381 mysql  cwd    DIR              253,1      4096    636744 /var/lib/mysql
mysqld  1064381 mysql  rtd    DIR              253,1       244       128 /
mysqld  1064381 mysql  txt    REG              253,1 251816000  51228705 /usr/sbin/mysqld
mysqld  1064381 mysql  mem    REG              253,1    553480  50342901 /usr/lib64/libpcre2-8.so.0.7.1
mysqld  1064381 mysql  mem    REG              253,1    304848  50342907 /usr/lib64/libselinux.so.1

(三)查看指定名称的进程所打开的文件列表

查看进程 mysqld 所打开的全部文件列表:

[root@htlwk0001host ~]# lsof -c mysqld
COMMAND     PID  USER   FD   TYPE             DEVICE  SIZE/OFF      NODE NAME
mysqld  1064381 mysql  cwd    DIR              253,1      4096    636744 /var/lib/mysql
mysqld  1064381 mysql  rtd    DIR              253,1       244       128 /
mysqld  1064381 mysql  txt    REG              253,1 251816000  51228705 /usr/sbin/mysqld
mysqld  1064381 mysql  mem    REG              253,1    553480  50342901 /usr/lib64/libpcre2-8.so.0.7.1
mysqld  1064381 mysql  mem    REG              253,1    304848  50342907 /usr/lib64/libselinux.so.1
mysqld  1064381 mysql  mem    REG              253,1     33224  50343274 /usr/lib64/libuuid.so.1.3.0

-c 选项限定只列出以 mysqld 开头的进程打开的文件:

你同样可以制定多个 -c 参数:

[root@htlwk0001host ~]# lsof -c apache -c python

这会列出所有由 apache 和 python 打开的文件。

(四)列出除了某个用户以外的被打开的文件列表

[root@htlwk0001host ~]# lsof -u ^root
COMMAND       PID     TID TASKCMD              USER   FD      TYPE             DEVICE  SIZE/OFF      NODE NAME
polkitd       715                           polkitd  cwd       DIR              253,1       244       128 /
polkitd       715                           polkitd  rtd       DIR              253,1       244       128 /

说明:^ 符号,表示 取反 的意思。

(五)列出除了某个进程之外,其它进程打开的文件列表

[root@htlwk0001host ~]# lsof -p ^1234

(六)列出所有的网络连接

列出所有打开了网络套接字(TCP和UDP)的进程:

[root@htlwk0001host ~]# lsof -i
COMMAND       PID            USER   FD   TYPE   DEVICE SIZE/OFF NODE NAME
chronyd       743          chrony    5u  IPv4    20334      0t0  UDP localhost:323 
chronyd       743          chrony    6u  IPv6    20335      0t0  UDP localhost:323 
NetworkMa     901            root   24u  IPv4    22817      0t0  UDP htlwk0001host:bootpc->_gateway:bootps 
systemd-r     955 systemd-resolve   12u  IPv4    23063      0t0  UDP *:hostmon 
systemd-r     955 systemd-resolve   13u  IPv4    23064      0t0  TCP *:hostmon (LISTEN)

(七)列出所有的 TCP 网络连接

[root@htlwk0001host ~]# lsof -i tcp
COMMAND       PID            USER   FD   TYPE   DEVICE SIZE/OFF NODE NAME
systemd-r     955 systemd-resolve   13u  IPv4    23064      0t0  TCP *:hostmon (LISTEN)
systemd-r     955 systemd-resolve   15u  IPv6    23067      0t0  TCP *:hostmon (LISTEN)
nginx       26556            root    8u  IPv4   137518      0t0  TCP *:http (LISTEN)
nginx       26556            root    9u  IPv4   137519      0t0  TCP *:https (LISTEN)
nginx       26556            root   10u  IPv6   137520      0t0  TCP *:https (LISTEN)
nginx       26556            root   11u  IPv6   137521      0t0  TCP *:http (LISTEN)
svnserve    34295            root    3u  IPv4   182743      0t0  TCP *:svn (LISTEN)
httpd       34871            root    4u  IPv6   186113      0t0  TCP *:tproxy (LISTEN)

tcp 选项会强制 lsof 只列出打开 TCP sockets 的进程。

(八)列出所有的 UDP 网络连接

[root@htlwk0001host ~]# lsof -i udp
COMMAND   PID            USER   FD   TYPE DEVICE SIZE/OFF NODE NAME
chronyd   743          chrony    5u  IPv4  20334      0t0  UDP localhost:323 
chronyd   743          chrony    6u  IPv6  20335      0t0  UDP localhost:323 
NetworkMa 901            root   24u  IPv4  22817      0t0  UDP htlwk0001host:bootpc->_gateway:bootps 
systemd-r 955 systemd-resolve   12u  IPv4  23063      0t0  UDP *:hostmon 
systemd-r 955 systemd-resolve   14u  IPv6  23066      0t0  UDP *:hostmon 
systemd-r 955 systemd-resolve   18u  IPv4  23069      0t0  UDP 127.0.0.53:domain 

(九)查看有哪些进程在使用指定的端口

lsof 列出占用 TCPUDP3306 端口的进程:

[root@htlwk0001host ~]# lsof -i:3306
COMMAND     PID  USER   FD   TYPE   DEVICE SIZE/OFF NODE NAME
java    1050299  root   72u  IPv6 19427946      0t0  TCP htlwk0001host:60664->47.114.59.224:mysql (ESTABLISHED)
java    1050299  root   78u  IPv6 19427982      0t0  TCP htlwk0001host:60704->47.114.59.224:mysql (ESTABLISHED)
java    1050299  root   79u  IPv6 19427963      0t0  TCP htlwk0001host:60684->47.114.59.224:mysql (ESTABLISHED)
java    1050299  root   80u  IPv6 19427972      0t0  TCP htlwk0001host:60696->47.114.59.224:mysql (ESTABLISHED)

你也可以使用 /etc/services 中制定的端口名称来代替端口号,比如:

[root@htlwk0001host ~]# lsof -i :smtp

(十)查看哪些进程在使用指定的 UDP 端口

[root@htlwk0001host ~]# lsof -i udp:55

(十一)查看哪些进程在使用指定的 TCP 端口

[root@htlwk0001host ~]# lsof -i tcp:55

(十二)列出某个用户所有活跃的网络端口

[root@htlwk0001host ~]# lsof -a -u test -i

(十三)查看指定用户组所打开的文件列表

查找所有 PGID 为 5555 的进程打开的文件:

[root@htlwk0001host ~]# lsof -g 5555;

(十四)根据文件描述符的范围查看有关的文件列表

  1. 显示使用 fd 为 2-3 的进程:
[root@htlwk0001host ~]# lsof -d 2-3
COMMAND       PID            USER   FD      TYPE             DEVICE  SIZE/OFF      NODE NAME
systemd         1            root    2u      CHR                1,3       0t0      6597 /dev/null
systemd         1            root    3w      CHR               1,11       0t0      6603 /dev/kmsg

上面的命令会列出所有描述符为 2 或 3 的文件。

  1. 显示使用 fd 为 4 的进程:
[root@htlwk0001host ~]# lsof -d 4
COMMAND       PID            USER   FD      TYPE             DEVICE SIZE/OFF     NODE NAME
systemd         1            root    4u  a_inode               0,14        0     9454 [eventpoll]
systemd-j     560            root    4u     unix 0xffff944b07050480      0t0    11200 /run/systemd/journal/socket type=DGRAM
systemd-u     587            root    4u  netlink                         0t0    17814 KOBJECT_UEVENT
auditd        673            root    4u     unix 0xffff944b2d4e8d80      0t0   380481 type=STREAM

上面这个命令会列出所有以描述符 4 打开的文件。

(十五)哪些进程在使用 apache 的可执行文件

[root@htlwk0001host ~]# lsof `which httpd`
COMMAND     PID   USER  FD   TYPE DEVICE SIZE/OFF     NODE NAME
httpd     34871   root txt    REG  253,1   580064 53187782 /usr/sbin/httpd
httpd   1048930 apache txt    REG  253,1   580064 53187782 /usr/sbin/httpd
httpd   1048931 apache txt    REG  253,1   580064 53187782 /usr/sbin/httpd
httpd   1049032 apache txt    REG  253,1   580064 53187782 /usr/sbin/httpd
httpd   1049033 apache txt    REG  253,1   580064 53187782 /usr/sbin/httpd
httpd   1049411 apache txt    REG  253,1   580064 53187782 /usr/sbin/httpd

(十六)查看连接到某个远程主机端口的进程

  1. 哪些进程打开了到 www.dpqyw.com 的UDP 端口 8088(ntp) 的连接:
[root@htlwk0001host ~]# lsof -i UDP@www.dpqyw.com:8088
  1. 哪些进程打开了到 192.168.2.245 TCP 端口 1521 的连接:
[root@svr-db-test ~]# lsof -i tcp@192.168.2.245:1521 -n

lsof -n 不将IP转换为hostname,缺省是不加上-n参数。

(十七)不断查看远程主机 ftp 连接的情况

[root@htlwk0001host ~]# lsof -i tcp@www.dpqyw.com:ftp -r -n
=======
=======
=======

说明:

  1. -rlsof 会永远不断的执行,直到收到中断信号
  2. +rlsof 会一直执行,直到没有档案被显示,缺省是 15s 刷新
  3. -n 不将 IP 转换为 hostname,缺省是不加上 -n 参数

(十八)递归查找某个目录中所有打开的文件

[root@htlwk0001host ~]# lsof +D /usr/lib

加上+D 参数,lsof 会对指定目录进行递归查找,注意这个参数要比 grep 版本慢:

[root@htlwk0001host ~]# lsof | grep '/usr/lib'

之所以慢是因为+D首先查找所有的文件,然后一次性输出。

(十九)列出某个用户打开的所有文件

[root@htlwk0001host ~]# lsof -u liaowenxiong

-u 选项限定只列出所有被用户 liaowenxiong 打开的文件,你可以通过逗号指定多个用户:

[root@htlwk0001host ~]# lsof -u liaowenxiong,liudehua

这条命令会列出 liaowenxiong 和 liudehua 用户打开的所有文件。

你也可以像下面这样使用多个 -u 做同样的事情:

[root@htlwk0001host ~]# lsof -u liaowenxiong -u root

(二十)列出由某个用户或某个进程打开的所有文件

[root@htlwk0001host ~]# lsof -u pkrumins -c apache

你可以组合使用多个选项,这些选项默认进行 关联,也就是说上面的命令会输出由用户 pkrumins 或者进程 apache 打开的文件,若希望多个选项之间是 关联,可用加上选项 -a

(二十一)查看某个用户的所有网络连接

查看用户 root 的所有网络连接:

[root@htlwk0001host ~]# lsof -a -u root -i
COMMAND       PID USER   FD   TYPE   DEVICE SIZE/OFF NODE NAME
NetworkMa     901 root   24u  IPv4    22817      0t0  UDP htlwk0001host:bootpc->_gateway:bootps 
nginx       26556 root    8u  IPv4   137518      0t0  TCP *:http (LISTEN)
nginx       26556 root    9u  IPv4   137519      0t0  TCP *:https (LISTEN)
nginx       26556 root   10u  IPv6   137520      0t0  TCP *:https (LISTEN)

使用 -a-u-i 选项组合可以让 lsof 列出某个用户的所有网络行为。

(二十二)列出所有内存映射文件

[root@htlwk0001host ~]#  lsof -d mem

(二十三)列出所有加载在内存中并正在执行的进程

[root@htlwk0001host ~]# lsof -d txt

(二十四)查看使用网络资源的进程 pid

[root@htlwk0001host ~]# lsof -t -i

-t 选项输出进程的 PID,你可以将它和 -i 选项组合输出使用某个端口的进程的 PID,如下:

[root@htlwk0001host ~]# lsof -t -i:3306
1050299
1050398
1064381

(二十五)杀掉所有使用网络的进程

[root@htlwk0001host ~]# kill -9 'lsof -t -i'

(二十六)循环列出文件

[root@htlwk0001host ~]# lsof -r 1

-r 选项让 lsof 可以循环列出文件直到被中断,参数1 就是循环间隔时间是 1 秒,即循环周期是 1 秒,意思是每秒钟重复打印一次,这个选项最好同某个范围比较小的查询组合使用,比如用来监测用户的网络活动:

[root@htlwk0001host ~]# lsof -r 1 -u john -i -a

(二十七)查看被打开的和网络相关的文件

使用 -i 选项用来查看网络相关的文件,其参数的格式如下:

lsof -i [46][protocol][@hostname|hostaddr][:service|port]

说明:

  1. 46 表示 IP 协议的版本
  2. protocol 表示网络协议的名称,比如 TCP 或 UDP
  3. hostnamehostaddr 表示主机域名或者主机 IP 地址
  4. service 指 /etc/services 中的端口名称,比如:smtp
  5. port 表示端口号,可以指定一个或多个

-i 选项默认会同时输出 IPv4 和 IPv6 打开的文件。

  1. 只列出 IPv4 或 IPv6 打开的文件:
[root@htlwk0001host ~]# lsof -i 4
[root@htlwk0001host ~]# lsof -i 6
  1. 列出占用一定端口范围的所有的进程:
[root@htlwk0001host ~]#lsof -i TCP:1-1024

(二十八)统计系统打开的文件总数

[root@htlwk0001host ~]# lsof -P -n | wc -l
69360

命令中的 -P 选项表示不解析端口号,-n 选项表示不解析主机名,这两个选项主要的目的是为了提升 lsof 命令的执行速度。wc -l 命令则用来统计 lsof 命令输出的行数。

(二十九)杀掉属于某个用户的打开了文件的所有进程

[root@htlwk0001host ~]# kill -9 `lsof -t -u nick`
[root@htlwk0001host ~]# kill -9 $(lsof -t -u nick)

(三十)列出某个 IP 的网络连接信息

[root@htlwk0001host ~]# lsof -i @47.114.59.256
COMMAND     PID  USER   FD   TYPE   DEVICE SIZE/OFF NODE NAME
java    1050299  root   72u  IPv6 19473546      0t0  TCP htlwk0001host:36448->47.114.59.224:mysql (ESTABLISHED)
java    1050299  root   78u  IPv6 19472650      0t0  TCP htlwk0001host:36488->47.114.59.224:mysql (ESTABLISHED)
java    1050299  root   79u  IPv6 19473549      0t0  TCP htlwk0001host:36450->47.114.59.224:mysql (ESTABLISHED)

(三十一)同时列出连接某主机多个端口的网络连接文件

列出目前连接主机 hadoop 的端口为:20,21,22,25,53,80 的所有文件信息,且每隔3秒不断的执行 lsof 指令:

[root@htlwk0001host ~]# lsof -i @hadoop:20,21,22,25,53,80  -r  3

经典场景应用

(一)查看指定进程打开的特定文件(查看日志文件路径)

场景描述:

同事今天请假了,但负责的 webserver 服务出现了问题,老板让你看一下 webserver 服务的日志,但你不知道 webserver 服务的日志文件路径,配置文件太复杂你不太懂,这时你可以执行以下命令查看日志文件路径。

[devl@xungen ~]$ lsof -c webserver | grep -e 'log$'
webserver  10124  devl  4u  REG 253,1  8814787  109523 /home/devl/application/webserver/log/webserver.00.log

(二)查看文件的内存映射路径(查看已删除文件的内容)

场景描述:

新来的同事误删除了 webserver 服务的日志文件,现在线上环境出现问题,需要查看 webserver 的日志,老板让紧急处理一下,这时你只能通过日志文件的内存映射路径来查看日志内容,那么怎么获取文件的内存映射路径呢?你要记住内存映射路径的固定格式:/proc/进程ID/fd/句柄。接着你要知道 webserver 进程 ID 和日志文件的句柄,那么这时我们就可以使用命令 lsof,来查看进程ID和文件句柄了。

注意:文件句柄又叫文件描述符又叫文件号

[devl@xungen ~]$ lsof -c webserver | grep -e 'log$'
webserver  10124  devl  4u  REG 253,1  8814787  109523 /home/devl/application/webserver/log/webserver.00.log

以上的执行结果显示 webserver 服务的进程 ID 为 10124,日志文件句柄为 4u(即 4 号句柄),所以 /proc/10124/fd/4 就是日志文件(webserver.00.log)在 webserver 进程中的内存映射路径,这时你用 tail 命令就可查看日志文件了。

[devl@xungen ~]$ tail -f /proc/10124/fd/4
[20190602 09:51:04|INF] start route ping process success
[20190602 09:51:04|INF] ping host[127.0.0.1:8888][3951] success
[20190602 09:51:09|INF] check session success
[20190602 09:51:09|INF] start route ping process success
[20190602 09:51:09|INF] ping host[127.0.0.1:8888][3596] success
[20190602 09:51:14|INF] start route ping process success
[20190602 09:51:14|INF] ping host[127.0.0.1:8888][3390] success
[20190602 09:51:19|INF] start route ping process success
[20190602 09:51:19|INF] ping host[127.0.0.1:8888][3383] success
[20190602 09:51:19|INF] check session success

扩展知识:

当进程打开了某个文件时,只要该进程保持打开该文件,即使将其删除,它依然存在于磁盘中。这意味着,进程并不知道文件已经被删除,它仍然可以向打开该文件时提供给它的文件描述符进行读取和写入。除了该进程之外,这个文件是不可见的,因为已经删除了其相应的目录索引节点。 在 /proc 目录下存储着反映内核和进程树的各种文件。/proc 目录挂载的是在内存中所映射的一块区域,所以这些文件和目录并不存在于磁盘中,因此当我们对这些文件进行读取和写入时,实际上是从内存中获取相关信息。大多数与 lsof 相关的信息都存储于以进程 ID 命名的目录中,例如: /proc/1234 中存储的是 PID 为 1234 的进程的信息。每个进程目录中存储着各种文件,它们可以使得应用程序简单地了解进程的内存空间、文件描述符列表、指向磁盘上的文件的符号链接和其他系统信息。

(三)恢复被删除的文件

当系统中的某个文件被意外地删除了,只要这个时候系统中还有进程正在访问该文件,那么我们就可以通过 lsof/proc 目录下恢复该文件的内容。 假如,由于误操作将 /var/log/messages 文件删除掉了,那么这时要将 /var/log/messages 文件恢复的方法如下:

首先使用 lsof 来查看当前是否有进程打开 /var/logmessages 文件,如下:

[root@htlwk0001host ~]# lsof |grep /var/log/messages 
syslogd 1283 root 2w REG 3,3 5381017 1773647 /var/log/messages (deleted)

从上面的信息可以看到进程 syslogd(PID=1283)打开文件的文件描述符为 2w。同时还可以看到 /var/log/messages 已经标记被删除了。因此我们可以在 /proc/1283/fd/2 中查看相应的信息,如下:

[root@htlwk0001host ~]# head -n 10 /proc/1283/fd/2 
Aug 4 13:50:15 holmes86 syslogd 1.4.1: restart. 
Aug 4 13:50:15 holmes86 kernel: klogd 1.4.1, log source = /proc/kmsg started. 
Aug 4 13:50:15 holmes86 kernel: Linux version 2.6.22.1-8 (root@everestbuilder.linux-ren.org) (gcc version 4.2.0) 
1 SMP Wed Jul 18 11:18:32 EDT 2007 
Aug 4 13:50:15 holmes86 kernel: BIOS-provided physical RAM map: 
Aug 4 13:50:15 holmes86 kernel: BIOS-e820: 0000000000000000 - 000000000009f000 (usable) 
Aug 4 13:50:15 holmes86 kernel: BIOS-e820: 000000000009f000 - 00000000000a0000 (reserved) 
Aug 4 13:50:15 holmes86 kernel: BIOS-e820: 0000000000100000 - 000000001f7d3800 (usable) 
Aug 4 13:50:15 holmes86 kernel: BIOS-e820: 000000001f7d3800 - 0000000020000000 (reserved) 
Aug 4 13:50:15 holmes86 kernel: BIOS-e820: 00000000e0000000 - 00000000f0007000 (reserved) 
Aug 4 13:50:15 holmes86 kernel: BIOS-e820: 00000000f0008000 - 00000000f000c000 (reserved)

如果可以通过文件描述符查看相应的数据,那么就可以使用 I/O 重定向将其复制到文件中,命令语句如下:

[root@htlwk0001host ~]# cat /proc/1283/fd/2 > /var/log/messages

或者

[root@htlwk0001host ~]# sh -c 'cat /proc/1283/fd/2 > /var/log/messages' 

然后修复文件的权限属性并重启 rsyslog 服务:

[root@htlwk0001host ~]# chown messages:adm /var/log/messages
[root@htlwk0001host ~]# systemctl restart rsyslog.service

这样就完成了 /var/log/messages 文件的恢复工作。对于许多应用程序,尤其是日志文件和数据库,这种恢复删除文件的方法非常有用。

(四) 日志文件删除后磁盘空间可用空间没有变大,怎么解决

发现文件系统 /tmp 目录下空间居然用满了,但用 du 命令统计 /tmp 目录中所有文件的大小,发现并没有大文件,怎么回事呢?出现这样的情况,很有可能是被删除的大文件依旧有其它程序在使用,所以依旧占用着磁盘空间,只是我们正常的方式无法查看到此文件,换句话说就是文件没有被彻底删除,这时候我们可以使用命令 lsof 求证下 。

步骤 1:查看系统磁盘的使用情况

[root@htlwk0001host ~]# df -h
Filesystem Size Used Avail Use% Mounted on
/dev/sda3 8.6G 1.5G 6.7G 18% /
/dev/sda10 784G 325G 420G 44% /u01
/dev/sda5 8.7G 7.9G 407M 96% /tmp
/dev/sda2 15G 2.8G 11G 21% /usr
/dev/sda1 122M 12M 104M 10% /boot
tmpfs 7.9G 4.0K 7.9G 1% /dev/shm

如上所示,/tmp 可用空剩下 407M

步骤 2:使用命令 lsof 查看正在被进程使用的与 /tmp 相关的文件

[root@htlwk0001host ~]# sudo lsof | grep /tmp
sleep 18833 peien.htg 1w REG 8,5 8321143673 54 /tmp/netstat.log (deleted)
netstat_2 13571 peien.htg 1w REG 8,5 8321143673 54 /tmp/netstat.log (deleted)
tcprstat 18823 root 2w REG 8,5 43632 49 /tmp/myrt.daemon.log
sh 18822 mysql 2w REG 8,5 43632 49 /tmp/myrt.daemon.log
sh 18822 mysql 1w REG 8,5 43632 49 /tmp/myrt.daemon.log
myrt.pl 26045 mysql 2w REG 8,5 43632 49 /tmp/myrt.daemon.log
myrt.pl 26045 mysql 1w REG 8,5 43632 49 /tmp/myrt.daemon.log
check_age 25298 mysql 2w REG 8,5 22049 33 /tmp/check_agent.log
check_age 25298 mysql 1w REG 8,5 22049 33 /tmp/check_agent.log
mysqld 3784 mysql 6u REG 8,5 15156 13 /tmp/ibH3IFN9 (deleted)

如上所示列表中的第二行,文件大小7个多G,文件标记已删,但是依旧被进程“netstat_2”占用,该进程的 PID=13571。

步骤 3: 我们可以使用命令 ps 查看进程更为详细的信息

[root@htlwk0001host ~]# ps -ef | grep 13571
51717 13571 1 0 2011 ? 00:15:00 /bin/bash /tmp/netstat_20110829.sh
51717 21456 13571 0 09:40 ? 00:00:00 sleep 10
zhuxu 21458 17014 0 09:40 pts/0 00:00:00 grep 13571

步骤 4:接着我们将此进程 kill 掉

[root@htlwk0001host ~]# sudo kill -9 13571

步骤 5:然后我们再看看那个已删的文件是否被进程占用着

[root@htlwk0001host ~]# sudo lsof | grep /tmp
tcprstat 22084 root 2w REG 8,5 49339 49 /tmp/myrt.daemon.log
sh 22083 mysql 2w REG 8,5 49339 49 /tmp/myrt.daemon.log
sh 22083 mysql 1w REG 8,5 49339 49 /tmp/myrt.daemon.log
myrt.pl 26045 mysql 2w REG 8,5 49339 49 /tmp/myrt.daemon.log
myrt.pl 26045 mysql 1w REG 8,5 49339 49 /tmp/myrt.daemon.log
check_age 25298 mysql 2w REG 8,5 24583 33 /tmp/check_agent.log
check_age 25298 mysql 1w REG 8,5 24583 33 /tmp/check_agent.log
mysqld 3784 mysql 6u REG 8,5 15156 13 /tmp/ibH3IFN9 (deleted)
su 17013 root cwd DIR 8,5 4096 2 /tmp
sort 22090 zhuxu cwd DIR 8,5 4096 2 /tmp

如上所示结果,看不到那个已删的大文件了。

步骤 6:我们再看看系统磁盘分区的使用情况,确认下 /tmp 的使用空间是否增加了

[root@htlwk0001host ~]# df -h
Filesystem Size Used Avail Use% Mounted on
/dev/sda3 8.6G 1.5G 6.7G 18% /
/dev/sda10 784G 325G 420G 44% /u01
/dev/sda5 8.7G 56M 8.2G 1% /tmp
/dev/sda2 15G 2.8G 11G 21% /usr
/dev/sda1 122M 12M 104M 10% /boot
tmpfs 7.9G 4.0K 7.9G 1% /dev/shm

如上所示,目录 /tmp 的可用空间变成 8.2G 了。

关注
打赏
查看更多评论

liaowenxiong

暂无认证

  • 3浏览

    0关注

    1033博文

    0收益

  • 0浏览

    0点赞

    0打赏

    0留言

私信
关注
热门博文
立即登录/注册

微信扫码登录