Linux命令--lsof
一前言
本文深入的学习命令lsof--列出打开文件(lists openfiles)。在linux系统中,我们可以通过 文件 访问文本数据,还可以访问网络连接和硬件。我们通过 lsof 命令可以查看进程开打了哪些文件,打开指定文件的进程有哪些,进程打开的端口(TCP、UDP)。找回/恢复删除的文件。
二 lsof 用法
权限需求
因为lsof命令需要访问核心内存和各种文件,所以需要具有root权限才能执行。
常用命令参数
usage: [-?abhlnNoOPRtUvVX] [+|-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]
关键选项
默认:没有选项,lsof 列出活跃进程的所有打开文件 组合:可以将选项组合到一起,如-a,但要当心哪些选项需要参数。 -a:结果进行"与"运算,比如 -abc 表示bc参数都必须满足时才显示结果。 -l:在输出显示用户ID而不是用户名。 -t:仅获取活跃的进程ID -U:获取UNIX套接口地址 -F:格式化输出结果,用于其它命令。可以通过多种方式格式化,如-F pcfn(用于进程id、命令名、文件描述符、文件名,并以空终止) -i:[46] [protocol][@hostname|hostaddr][:service|port] 46 --> IPv4 or IPv6 protocol --> TCP or UDP hostname --> 主机名 hostaddr --> IPv4地址 service --> /etc/service中的 service name (可以多个) port --> 端口号 (可以多个) -c string 显示COMMAND列中包含指定字符的进程所有打开的文件 -u username 显示所属user进程打开的文件 +d /DIR/ 显示目录下被进程打开的文件 +D /DIR/ 同上,但是会搜索目录下的所有目录,时间相对较长 -d FD 显示指定文件描述符的进程 -n 不将IP转换为hostname,缺省是不加上-n参数
输出解析
我们查看 mysqld_safe 进程打开的文件。
COMMAND: 进程的名称 PID: 进程标识符 PPID: 父进程标识符(需要指定-R参数) USER: 进程所有者 FD: 文件描述符,应用程序通过文件描述符识别该文件。如cwd,txt等 TYPE: 文件类型,DIR, REG TYPE:文件类型,如DIR、REG等,常见的文件类型 SIZE: 文件的大小,如果没有则为空 NODE: 索引节点(文件在磁盘上的标识) NAME: 打开文件的具体名称
其中 FD 文件描述符:
cwd值表示应用程序的当前工作目录。 txt 类型的文件是程序代码,如应用程序二进制文件本身或共享库 0:表示标准输出 1:表示标准输入 2:表示标准错误 一般在标准输出、标准错误、标准输入后还跟着文件状态模式:r、w、u等 u:表示该文件被打开并处于读取/写入模式 r:表示该文件被打开并处于只读模式 w:表示该文件被打开并处于 空格:表示该文件的状态模式为unknow,且没有锁定 -:表示该文件的状态模式为unknow,且被锁定
TYPE 类型的详细介绍
DIR:表示目录 CHR:表示字符类型 BLK:块设备类型 UNIX: UNIX 域套接字 FIFO:先进先出 (FIFO) 队列 IPv4:网际协议 (IP) 套接字
三 常见用法
使用-u显示指定用户打开了什么(文件和网络连接)
lsof -u mysql
找到某个用户的所有网络连接
lsof -a -u mysql -i
使用-a将-u和-i选项组合可以让lsof列出某个用户的所有网络行为。
使用-i:port来显示与指定端口相关的网络信息
lsof -i:22
使用@host来显示指定到指定主机的连接
lsof @10.215.20.13
仅显示TCP连接(同理可获得UDP连接)
lsof -iTCP
使用-c查看指定的命令正在使用的文件和网络连接
lsof -c mysqld_safe
显示与指定目录交互的所有一切
lsof sandboxes/msb 5 7_19/data
COMMAND PID USER FD TYPE DEVICE SIZE/OFF NODE NAME mysqld 30315 root cwd DIR 8,1 4096 38684532 sandboxes/msb_5_7_19/data
恢复删除的文件
我们删除 sandbox构造的数据库的日志文件 msandbox.err 1.获取哪些进程在使用
[root@r1db7 21:03:06 ~/sandboxes/msb_5_7_19/data] # lsof msandbox.err COMMAND PID USER FD TYPE DEVICE SIZE/OFF NODE NAME mysqld 30315 root 1w REG 8,1 25940690 38684533 msandbox.err mysqld 30315 root 2w REG 8,1 25940690 38684533 msandbox.err
2.删除文件
rm msandbox.err
3.再次查看 该文件已经被标记为 deleted 状态
# lsof | grep msandbox.err mysqld 30315 root 2w REG 8,1 25940690 38684533 /root/sandboxes/msb_5_7_19/data/msandbox.err (deleted)
4.恢复
[root@r1db7 21:04:00 ~/sandboxes/msb_5_7_19/data] # cat /proc/30315/fd/2 > msandbox.err
另外需要注意的是如果删除的文件不需要恢复而且占用非常多的空间,那么我们可以通过如下方法解决。
1 查看占用该文件的进程,杀掉该进程,文件句柄被释放,释放空间。 2 遇到僵死进程时,kill或kill -9命令是无法结束该进程的,只有重启服务器,杀死进程,释放空间。