Linux常用命令--lsof
摘要
-
本文介绍 lsof 命令的使用方法
-
本文基于CentOS8。
lsof 是什么?
-
lsof = list open files
-
它用来查看:
- 当前系统中所有进程打开的文件
- 包含普通文件、目录、socket、管道、网络连接、设备等
-
在 Linux 中:“一切皆文件”
-
所以你可以用 lsof 查看:
- 谁在占用你的端口?
- 哪个进程正在读/写某个文件?
- 为什么文件删除了却还占磁盘?
- 哪个文件被锁住?
- 哪些程序在访问某个目录?
-
CentOS 默认包含 lsof,但如果没有,可以通过 yum 安装
1 | yum install lsof -y |
lsof 的基本用法
查看被删除但仍被占用的文件
-
如果进程正在运行且保持文件的句柄,此时没有停止进程就执行了
rm命令,此时文件的**目录项(名字)**被删除,但是文件数据本身没有被删除,只要有进程还在打开这个文件(保持文件句柄),它就继续占用磁盘空间。 -
文件已经被删除(unlink),但进程仍然持有该文件的打开句柄,这种文件在:
1 | ls 中看不到 |
-
此时可以通过如下命令查询哪些被删除的文件还被占用:
1 | # 列出所有 link count 小于 1 的(deleted)文件 |
-
如果查询到这种文件,则需要停止进程,才能真正删除文件。
记一次线上服务器磁盘空间告警问题排查
- 监控系统告警磁盘空间小于15%,通过如下命令查看确实如此
1 | $ df -hT |
- 但通过如下命令具体查看目录占用空间时,发现占用的空间比实际占用的空间少很多
1 | $ du -sh /usr/local/boss/logs |
- 此时想到可能是删除的文件句柄没有被释放,可以通过如下命令查看:
1 | lsof +L1 |
- 结果如预期,这是一个tomcat进程,应该是删除了其日志文件,但是删除时没有停止tomcat进程,导致文件被继续占用,此时已经占用了80多个G的磁盘空间,如果要释放磁盘空间需要停止tomcat。
查端口被哪个进程占用
-
通过如下命令查询:
1 | # 列出指定端口对应的进程 |
查看某个进程打开的所有文件
-
通过如下命令查询:
1 | lsof -p <PID> |
-
能看到这个进程:
- 打开的日志文件
- 使用的 jar 文件
- 使用的 socket
- 使用的 config 文件
-
输出结果字段说明
| 字段 | 含义 |
|---|---|
| COMMAND | 程序名(java) |
| PID | 进程号(18548) |
| USER | 运行用户(boss) |
| FD | 文件描述符 |
| TYPE | 文件类型 |
| DEVICE | 所在磁盘分区 ID |
| SIZE/OFF | 文件大小(字节) |
| NODE | inode 编号 |
| NAME | 文件名(或网络连接信息) |
查看指定用户占用的文件
-
通过如下命令查询:
1 | # 列出用户 boss 所有进程打开的文件 |
查看指定程序(COMMAND)打开的文件
-
通过如下命令查询:
1 | lsof -c <command> |
查某个目录或文件正在被哪些进程占用
1 | # 目录 +D |
查看网络连接
1 | lsof -i |
常用参数详解
| 参数 | 作用 | 示例 |
|---|---|---|
-i |
查看网络相关文件/端口 | lsof -i |
-i :端口 |
查看指定端口 | lsof -i :8080 |
-p PID |
查看某个进程所有打开文件 | lsof -p 1836 |
-u 用户名 |
查看某个用户进程的打开文件 | lsof -u nginx |
-c 进程名关键字 |
查看某个进程名相关的文件 | lsof -c java |
+D 目录 |
查看目录中所有被访问的文件 | lsof +D /usr/local/netqin/boss/netqin/logs |
+L1 |
查找已删除但仍被打开的文件 | lsof +L1(=查找“(deleted)”占盘问题) |
-d FD |
查看指定文件描述符 | lsof -d 1 -p 1836(看进程 stdout) |
-n |
不做 DNS 解析,提高速度 | lsof -i -n |
-P |
显示端口号(不解析为服务名) | lsof -i -P |
-s |
按连接状态过滤(TCP/UDP) | lsof -i -sTCP:LISTEN |
-r |
持续输出(实时监控) | lsof -i -r 1(每秒刷新网络连接) |
-a |
逻辑 AND,不加 -a 都是 逻辑 OR | lsof -u boss -i(列出用户 boss 的网络连接) |
lsof 文件 FD 字段详细解释
-
FD(文件描述符)格式总规则:数字 + 标志位
-
lsof 输出中的 FD(文件描述符)列,每一个都代表进程打开的一个“文件”(包括普通文件、目录、设备、socket、pipe 等)。
-
示例
1 | 10r → FD=10,read only(只读) |
-
解释
| 部分 | 含义 |
|---|---|
| 数字(0、1、2、3、10、36…) | 文件描述符编号 |
| 字母(r / w / u) | 访问模式:读/写/读写 |
| FD 编号 | 标准含义 |
|---|---|
| 0 | stdin(标准输入) |
| 1 | stdout(标准输出) |
| 2 | stderr(标准错误输出) |
| 3 及以上 | 进程打开的普通文件、日志、socket、管道等 |
-
特殊 FD 类型(没有数字)
| 字段 | 含义 |
|---|---|
cwd |
当前工作目录,说明进程在这个目录下运行 |
rtd |
进程的根目录,大多数情况下是 /,容器里可能是别的 rootfs |
txt |
可执行文件本体 |
mem |
内存映射(mmap)文件,进程加载到内存中的库 / jar / so 文件 |
lsof 文件 TYPE 字段详细解释
| 文件类型 | 全称 | 含义 | 常见场景 |
|---|---|---|---|
| REG | Regular file | 普通文件 | 日志、配置、可执行程序等 |
| DIR | Directory | 目录 | 进程访问的目录,例如当前工作目录 |
| CHR | Character special file | 字符设备文件 | /dev/null、/dev/tty、串口、键盘等 |
| BLK | Block special file | 块设备文件 | /dev/sda、硬盘、分区等 |
| FIFO | Named pipe | 命名管道 | Linux 进程间通信,如 Nginx 和 PHP-FPM 的通信 |
| sock | Socket | 套接字(Unix 域 socket) | /var/run/docker.sock、MySQL UNix socket |
| IPv4 | IPv4 socket | IPv4 网络连接/监听 | TCP *:80、UDP 127.0.0.1:53 |
| IPv6 | IPv6 socket | IPv6 网络连接/监听 | TCP [::]:22 |
| unix | Unix domain socket | 本地进程通信 | /run/systemd/journal/stdout |