linux性能检测之lsof详解
一、lsof 介绍
lsof是一个列出当前系统打开文件的工具。在linux系统中,一切皆文件。所以我们可以用lsof查看网络连接或者查看进程打开的文件等,很强大的一个工具。
lsof的格式:
lsof [ -?abChlnNOPRtUvVX ] [ -A A ] [ -c c ] [ +c c ] [ +|-d d ] [ +|-D D ] [ +|-e s ] [ +|-f [cfgGn] ] [ -F [f] ] [ -g [s] ] [ -i [i] ] [ -k k ] [ +|-L [l] ] [ +|-m m ] [ +|-M ] [ -o [o] ] [
-p s ] [ +|-r [t[m<fmt>]] ] [ -s [p:s] ] [ -S [t] ] [ -T [t] ] [ -u s ] [ +|-w ] [ -x [fl] ] [ -z [z] ] [ -Z [Z] ] [ -- ] [names]
下面是在终端下输入lsof命令,即可显示系统打开的文件(因为lsof需要访问核心内存和各种文件,一半root用户才能执行lsof命令):
# lsof|head -10
COMMAND PID USER FD TYPE DEVICE SIZE/OFF NODE NAME
init 1 root cwd DIR 252,3 4096 2 /
init 1 root rtd DIR 252,3 4096 2 /
init 1 root txt REG 252,3 150352 11010075 /sbin/init
init 1 root mem REG 252,3 65960 786464 /lib64/libnss_files-2.12.so
init 1 root mem REG 252,3 1923352 786448 /lib64/libc-2.12.so
init 1 root mem REG 252,3 90880 786434 /lib64/libgcc_s-4.4.7-20120601.so.1
init 1 root mem REG 252,3 43944 786476 /lib64/librt-2.12.so
init 1 root mem REG 252,3 142688 786472 /lib64/libpthread-2.12.so
init 1 root mem REG 252,3 265728 786500 /lib64/libdbus-1.so.3.4.0
#COMMAND:进程的名称
#PID:进程标识符
#USER:进程所有者
#FD:文件描述符,应用程序通过文件描述符识别该文件。如cwd、txt等
#TYPE:文件类型,如DIR、REG等
#DEVICE:指定磁盘的名称
#SIZE:文件的大小
#NODE:索引节点(文件在磁盘上的标识)
#NAME:打开文件的确切名称
FD列值的含义与fuser查询结果中PID后接字符的含义相同,指示了进程与文件的关联关系,有以下常见取值:
cwd:进程工作目录
txt:进程由该文件拉起(如二进制文件或脚本)
rtd:进程的根目录
mem:内存映射文件
N(u/w/r):指示该文件为进程打开的第N个文件描述符,u为可读可写模式,w为可写模式,r为可读模式
TYPE列有以下常见取值:
REG:一般文件
DIR:目录
CHR:字符设备
BLK:块设备
FIFO:命名管道
PIPE:管道
IPV4:ipv4套接字
unix:unix域套接字
博文来自:www.51niux.com
二、部分选项介绍
-h : 查看帮助说明
-a : 精确匹配,AND选项,既符合什么又符合什么,如:lsof -u root -a -p 1584 (查看用户名为root,并且pid是1584,打开的文件)
-A : A此选项在为AFS配置的系统上可用,其AFS内核代码通过动态模块实现。它允许lsof用户将A指定为备用名称列表文件其中可以找到动态模块的内核地址。
-b :此选项使lsof避免可能阻塞的内核函数 - lstat(2),readlink(2)和stat(2)。
-u : 指定用户名或者用户ID(UID),来显示此用户打开的文件,如:lsof -u ntp或者lsof -u 38
-p :指定进程ID(PID),来查看此进程所打开的文件,如:lsof -p 1584
-c : 指定COMMAND进程名称,来查看此进程打开的文件,如:lsof -c java。如果c以斜杠('/')开头和结尾,斜杠之间的字符将被解释为正则表达式。正则表达式中的Shell元字符必须带引号以防止它们被解释。
-C :此选项禁用从内核名称缓存中报告任何路径名组件。
-d :FD以什么开头,如:lsof -d 6 (只会将FD那一列是以6开头的内容打印出来)
+d : 搜索指定目录的所有打开实例及其顶层包含的文件和目录,如:lsof +d /dev (将是NAME是/dev的内容打印出来)
+D :使lsof搜索指定目录的所有打开实例及其包含的完整深度的所有文件和目录,就类似于递归的形式,如果有多层目录都会显示出来。如:lsof +D /
-g :将PGID(PGID为进程所在的进程组的ID)为我们指定的内容打印出来,如: lsof -g 1 就是将PGID为1的打印出来
-i :选择任何其Internet地址与i中指定的地址匹配的文件的列表。 46指定IP版本,IPv4或IPv6, 协议是一个协议名称 - TCP,UDP, hostname是Internet主机名, 服务是/ etc / services名称, 端口是端口号,或者它们的列表。hostaddr是一个数字Internet IPv4地址点形式;或IPv6中的IPv6数字地址.
-l: 显示用户的PID而非用户名
+/- r:后面跟数字,代表每个多少秒重新执行一次,这里如果是-r重复模式是无止境的。Lsof必须以中断或退出信号终止。如果是+r 重复直到由选项的前缀定义的条件停止。
-R:指示lsof列出PPID列中的父进程标识号。
-S:此选项为内核函数-lstat(2),readlink(2)和stat(2)指定可能超时秒值,否则可能会死锁。最小值为2;默认,15秒;当未指定值时,将使用缺省值。
-T :控制报告一些TCP / TPI信息,也由netstat(1)报告,遵循网络地址。 <TCP或TPI状态名称>:QR = <读队列长度>QS = <发送队列长度>SO = <套接字选项和值>SS = <套接字状态>TF = <TCP标志和值>
WR = <窗口读长度>WW = <窗口写长度>,q选择队列长度报告、s选择连接状态报告、w选择窗口大小报告、f选择报告套接字选项,状态和值,以及TCP标志和值
博文来自:www.51niux.com
三、示例演示
3.1 获取网络信息
#lsof -i #显示所有的连接
#lsof -i 6 #显示ipv6的连接
#lsof -i 4 #显示ipv4的连接
#lsof -iTCP #显示TCP的连接
#lsof -iUDP #显示UDP的连接
#lsof -i :22 #显示22端口的连接
#lsof -i :22,123 #显示22和123端口的连接
# lsof -i :1-1024 #显示1-1024端口的连接情况
# lsof -i@192.168.1.101 #显示192.168.1.101主机的连接
# lsof -i@192.168.1.130:51461 #显示来自于192.168.1.130的51461端口的连接
# lsof -i -sTCP:LISTEN #找出TCP的监听端口
# lsof -i -sTCP:ESTABLISHED #找出已建立连接的连接。
# lsof -i UDP:8668 #列出udp8668端口的连接
# lsof -i @www.baidu.com #显示哪个进程跟www.baidu.com在连接
COMMAND PID USER FD TYPE DEVICE SIZE/OFF NODE NAME
telnet 28552 root 3u IPv4 1281015 0t0 TCP 192.168.1.101:46010->119.75.217.109:http (ESTABLISHED)
3.2 显示打开了哪些文件
# lsof -u root #显示root用户打开的哪些文件
# lsof -u ^root #显示非root用户打开的文件
# lsof -p 28396 #显示pid进程28396所打开了哪些文件
#lsof -c java #查看java命令正在使用的文件和网络连接
# lsof -t -c bash #只返回bash命令现在进程的PID
27898
27956
28137
28343
# lsof /dev/pts/ #显示与指定目录/dev/pts目录交互的所有一切
# lsof +L2 #显示所有打开的链接数小于2的文件
# lsof -s #列出文件大小,如果文件没有大小就是空白
# kill -9 `lsof -t -u nobody` #杀死指定用户所运行的一切服务
# kill -HUP `lsof -t -c sshd` #给sshd进程发送HUP信号
# lsof -u root -a -d txt #显示用户名为root并且FD是txt类型的进程打开的文件,默认是-o
# lsof -n|awk '{print $2}'|sort|uniq -c|sort -nr|head -10 #查询文件句柄打开前十位的PID号,第一行为打开的文件句柄数量,第二行是进程号PID。
183 1652
172 1668
172 1667
172 1662
172 1661
172 1658
118 2272
114 1669
106 1650
101 1651
# lsof `which sshd` #查看哪个进程在使用sshd的可执行文件
COMMAND PID USER FD TYPE DEVICE SIZE/OFF NODE NAME
sshd 1519 root txt REG 8,3 526008 926152 /usr/sbin/sshd
sshd 2611 root txt REG 8,3 526008 926152 /usr/sbin/sshd
# lsof /etc/passwd #查看哪个进程在占用/etc/passwd文件
# lsof|grep -i delete #查看系统中又哪些被删除的文件,有的时候删除了文件但是进程没有reload,空间还是占用状态。会造成df -h 和du -sh 目录,显示不一致的问题。
小例子(文件删除未释放的磁盘占用):
生产过程中也经常会遇到,有些大文件删除了,但是还有好多程序在占用,导致磁盘空间没有释放,然后磁盘报警了,用df -h一查看确实磁盘空间不足了,然后du -sh 对应的目录发现一汇总也没占用多少空间啊。
#lsof |grep delete|awk {'print $(NF -1)'}|sort -nr|uniq #因为生产上一个文件可能有很多条占用,这样去重一下,可以就将被占用已经删除还没释放的文件列出来。然后我们就可以重启相关的服务来释放空间啦。
博文来自:www.51niux.com
四、恢复删除文件
当系统中的某个文件被以外删除,有时候可以通过lsof来恢复这些文件,当进程打开了某个文件时,只要该进程保持打开该文件,即使将其删除,它依然存在于磁盘中。这意味着,进程并不知道文件已经被删除,它仍然可以向打开该文件 时提供给它的文件描述符进行读取和写入。除了该进程之外,这个文件是不可见的,因为已经删除了其相应的目录索引节点。
在/proc 目录下,其中包含了反映内核和进程树的各种文件。/proc目录挂载的是在内存中所映射的一块区域,所以这些文件和目录并不存在于磁盘中,因此当我们对这 些文件进行读取和写入时,实际上是在从内存中获取相关信息。大多数与 lsof 相关的信息都存储于以进程的 PID 命名的目录中。
下面是将/var/log/messages日志文件删除并恢复的过程:
# cp /var/log/messages /opt/ #先将日志文件拷贝到其他目录一份等会用于比较
# rm -rf /var/log/messages #删除日志文件
# lsof |grep /var/log/messages #打开文件的描述符为1,文件已经被标记为删除了。PID为1287
rsyslogd 1287 root 1w REG 8,3 422884 399235 /var/log/messages (deleted)
# tail -n 10 /proc/1287/fd/1 #/proc/PID/fd/1中查看最后十条信息是最新的
Mar 20 22:56:45 master dnsmasq[2217]: compile time options: IPv6 GNU-getopt DBus no-I18N DHCP TFTP "--bind-interfaces with SO_BINDTODEVICE"
Mar 20 22:56:45 master dnsmasq-dhcp[2217]: DHCP, IP range 192.168.122.2 -- 192.168.122.254, lease time 1h
Mar 20 22:56:45 master dnsmasq[2217]: reading /etc/resolv.conf
Mar 20 22:56:45 master dnsmasq[2217]: using nameserver 202.106.0.20#53
Mar 20 22:56:45 master dnsmasq[2217]: read /etc/hosts - 11 addresses
Mar 20 22:56:45 master dnsmasq[2217]: read /var/lib/libvirt/dnsmasq/default.addnhosts - 0 addresses
Mar 20 22:56:45 master dnsmasq[2217]: read /var/lib/libvirt/dnsmasq/default.hostsfile
Mar 20 22:56:45 master kernel: Ebtables v2.0 registered
Mar 20 22:56:45 master kernel: ip6_tables: (C) 2000-2006 Netfilter Core Team
Mar 20 22:56:48 master kernel: lo: Disabled Privacy Extensions
# cat /proc/1287/fd/1 >/var/log/messages #将内容重定向回来
# diff /opt/messages /var/log/messages #跟提前拷贝的文件对比一下,文件内容没有差异