[Linux]命令lsof

409 阅读9分钟
  • 基于CentOS 6.9

简介

JX,SK的时候我们介绍过,如何来查看某个端口的状态。 比如常见的ssh协议用的22端口。

[root@testing ~]# lsof -i:22
COMMAND  PID USER   FD   TYPE DEVICE SIZE/OFF NODE NAME
sshd    1980 root    3u  IPv4  14767      0t0  TCP *:ssh (LISTEN)
sshd    1980 root    4u  IPv6  14772      0t0  TCP *:ssh (LISTEN)
sshd    2935 root    3r  IPv4  24579      0t0  TCP 172.20.254.119:ssh->172.20.254.153:49549 (ESTABLISHED)

从上面的输出可以看到22端口处于监听状态,而且已经有连接建立了。 当然还有另外的很多命令可以用来查看端口的状态,毕竟端口是个很重要的东西。比如ss和netstat(但这个是一个过时的命令)

[root@testing ~]# ss sport == :22
State      Recv-Q Send-Q              Local Address:Port                  Peer Address:Port   
ESTAB      0      52                 172.20.254.119:ssh                 172.20.254.153:49549

[root@testing ~]# netstat -anpl|grep :22
tcp        0      0 0.0.0.0:22                  0.0.0.0:*                   LISTEN      1980/sshd           
tcp        0     52 172.20.254.119:22           172.20.254.153:49549        ESTABLISHED 2935/sshd           
tcp        0      0 :::22                       :::*                        LISTEN      1980/sshd         

那lsof到底是什么意思呢?lsof可有大用呢。

参数

  1. 查看lsof的帮助
[root@testing ~]# man lsof
LSOF(8)                                                                LSOF(8)

NAME
       lsof - list open files

SYNOPSIS
       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的字面意思是列出打开的文件
  • lsof是:管理命令及守护进程
man帮助页说明
1、用户命令
2、系统调用
3、C库调用
4、设备文件及特殊文件
5、配置文件格式
6、游戏
7、杂项
8、管理命令及守护进程
9、Linux内核API(CentOS7以后出现)

示例1

既然lsof是列出打开的文件,为何能看到端口呢?那不要忘了,linux的哲学是:一切皆文件。 那我们还是先看看本源,打开的文件能否被看到呢?

开启2个终端,一个终端用more看文件(注意要文件内容多一些,不然就看完了),当然也可以用tail -f看。


[root@testing home]# more /etc/profile
# .bashrc
...
[root@testing home]# lsof /etc/profile
COMMAND  PID USER   FD   TYPE DEVICE SIZE/OFF   NODE NAME
more    3135 root    3r   REG    8,3     1841 392487 /etc/profile

证明没错,的确是可以看到打开文件的程序(more)的,这其实已经非常有用了,可以看到文件在被哪个进程使用,不就像windows下删除一个文件,却说文件被程序占用无法删除,但不借助一些工具解除占用的话(比如unlock、360)你不知道怎么去删除吗?在linux下直接可以用命令搞定,根本不需要什么工具的。

示例2

再来看一个例子,一个终端用vi打开一个文件

[root@testing home]# vi bashrc 

# .bashrc

# User specific aliases and functions

但是奇怪的事情来了,在另外一个终端执行lsof却看不到?

[root@testing home]# lsof bashrc 
[root@testing home]#

这是怎么回事? 我们在当前目录用ls -al查看所有文件能发现,有一个文件叫.bashrc.swp,这是个什么东西?

[root@testing home]# ls -al
total 644
drwxr-xr-x.  8 root       root         4096 Sep 21 08:50 .
dr-xr-xr-x. 25 root       root         4096 Sep 21 08:21 ..
-rw-r--r--.  2 root       root          176 Sep 20 09:22 bashrc
-rw-r--r--.  1 root       root        12288 Sep 21 08:50 .bashrc.swp

其实我们在vi basrc的时候是打开了一个.bashrc.swp的东西,这是用来临时交换的。这也是为什么,我们如果打开2次这个文件会有下面的提示的缘故。

[root@testing home]# vi bashrc 
E325: ATTENTION
Found a swap file by the name ".bashrc.swp"
          owned by: root   dated: Sat Sep 21 08:50:55 2019
         file name: /home/bashrc
          modified: no
         user name: root   host name: testing
        process ID: 3167 (still running)
While opening file "bashrc"
             dated: Fri Sep 20 09:22:53 2019

(1) Another program may be editing the same file.  If this is the case,
    be careful not to end up with two different instances of the same
    file when making changes.  Quit, or continue with caution.
(2) An edit session for this file crashed.
    If this is the case, use ":recover" or "vim -r bashrc"
    to recover the changes (see ":help recovery").
    If you did this already, delete the swap file ".bashrc.swp"
    to avoid this message.
"bashrc" 12L, 176C
Press ENTER or type command to continue

说到这里可能大概知道了,我们lsof没有失效,我们应该是lsof .bashrc.swp才能看到打开的文件

[root@testing home]# lsof |grep bashrc
vi        3167      root    4u      REG                8,3    12288     143517 /home/.bashrc.swp
[root@testing home]# lsof .bashrc.swp
COMMAND  PID USER   FD   TYPE DEVICE SIZE/OFF   NODE NAME
vi      3167 root    4u   REG    8,3    12288 143517 .bashrc.swp

lsof的常见用法1

lsof的参数那么多,是我们可以深究的一个命令,作用非常多且实用。

  • lsof 默认显示系统打开的所有文件,慎用,刷屏
[root@testing home]# lsof|more
COMMAND    PID      USER   FD      TYPE             DEVICE SIZE/OFF       NODE NAME
init         1      root  cwd       DIR                8,3     4096          2 /
init         1      root  rtd       DIR                8,3     4096          2 /
init         1      root  txt       REG                8,3   150352     130878 /sbin/init
init         1      root  mem       REG                8,3    66432     261666 /lib64/libnss_fil
es-2.12.so

这里我们要介绍下输出的含义,命令命令不知道输出什么含义,也不是白搭。

  • COMMAND:进程的名称
  • PID:进程标识符
  • USER:进程所有者
  • FD:文件描述符,应用程序通过文件描述符识别该文件。如cwd、txt等
  • TYPE:文件类型,如DIR、REG等
  • DEVICE:指定磁盘的名称
  • SIZE:文件的大小
  • NODE:索引节点(文件在磁盘上的标识)
  • NAME:打开文件的确切名称

文件描述符列表:

  1. cwd:表示current work dirctory,即:应用程序的当前工作目录,这是该应用程序启动的目录,除非它本身对这个目录进行更改
  2. txt:该类型的文件是程序代码,如应用程序二进制文件本身或共享库,如上列表中显示的 /sbin/init 程序
  3. lnn:library references (AIX);
  4. er:FD information error (see NAME column);
  5. jld:jail directory (FreeBSD);
  6. ltx:shared library text (code and data);
  7. mxx :hex memory-mapped type number xx.
  8. m86:DOS Merge mapped file;
  9. mem:memory-mapped file;
  10. mmap:memory-mapped device;
  11. pd:parent directory;
  12. rtd:root directory;
  13. tr:kernel trace file (OpenBSD);
  14. v86  VP/ix mapped file;
  15. 0:表示标准输出
  16. 1:表示标准输入
  17. 2:表示标准错误

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

  1. u:表示该文件被打开并处于读取/写入模式。
  2. r:表示该文件被打开并处于只读模式。
  3. w:表示该文件被打开并处于。
  4. 空格:表示该文件的状态模式为unknow,且没有锁定。
  5. -:表示该文件的状态模式为unknow,且被锁定。

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

  1. N:for a Solaris NFS lock of unknown type;
  2. r:for read lock on part of the file;
  3. R:for a read lock on the entire file;
  4. w:for a write lock on part of the file;(文件的部分写锁)
  5. W:for a write lock on the entire file;(整个文件的写锁)
  6. u:for a read and write lock of any length;
  7. U:for a lock of unknown type;
  8. x:for an SCO OpenServer Xenix lock on part      of the file;
  9. X:for an SCO OpenServer Xenix lock on the      entire file;
  10. space:if there is no lock.

文件类型:

  1. DIR:表示目录。
  2. CHR:表示字符类型。
  3. BLK:块设备类型。
  4. UNIX: UNIX 域套接字。
  5. FIFO:先进先出 (FIFO) 队列。
  6. IPv4:网际协议 (IP) 套接字。
  7. DEVICE:指定磁盘的名称
  8. SIZE:文件的大小
  9. NODE:索引节点(文件在磁盘上的标识)
  10. NAME:打开文件的确切名称

lsof的常见命令2(未考证)

2. 查看谁正在使用某个文件

lsof   /filepath/file

3.递归查看某个目录的文件信息

lsof +D /filepath/filepath2/

备注: 使用了+D,对应目录下的所有子目录和文件都会被列出

4. 比使用+D选项,遍历查看某个目录的所有文件信息 的方法

lsof | grep ‘/filepath/filepath2/’

5. 列出某个用户打开的文件信息

lsof  -u username

备注: -u 选项,u其实是user的缩写

6. 列出某个程序所打开的文件信息

lsof -c mysql

备注: -c 选项将会列出所有以mysql开头的程序的文件,其实你也可以写成**lsof | grep mysql,**但是第一种方法明显比第二种方法要少打几个字符了

7. 列出多个程序多打开的文件信息

lsof -c mysql -c apache

8. 列出某个用户以及某个程序所打开的文件信息

lsof -u test -c mysql

9. 列出除了某个用户外的被打开的文件信息

lsof   -u ^root

备注:^这个符号在用户名之前,将会把是root用户打开的进程不让显示

10. 通过某个进程号显示该进行打开的文件

lsof -p 1

11. 列出多个进程号对应的文件信息

lsof -p 123,456,789

12. 列出除了某个进程号,其他进程号所打开的文件信息

lsof -p ^1

13 . 列出所有的网络连接

lsof -i

14. 列出所有tcp 网络连接信息

lsof  -i tcp

15. 列出所有udp网络连接信息

lsof  -i udp

16. 列出谁在使用某个端口

lsof -i :3306

17. 列出谁在使用某个特定的udp端口

lsof -i udp:55

特定的tcp端口

lsof -i tcp:80

18. 列出某个用户的所有活跃的网络端口

lsof  -a -u test -i

19. 列出所有网络文件系统

lsof -N

20.域名socket文件

lsof -u

21.某个用户组所打开的文件信息

lsof -g 5555

22. 根据文件描述列出对应的文件信息

lsof -d description(like 2)

23. 根据文件描述范围列出文件信息

lsof -d 2-3