lsof命令
1. lsof的输出解释
lsof
(list open files)可以一次性列出 进程打开的所有文件、套接字、管道、设备,包含了这些进程的信息和打开文件的相关信息。文件主要是普通文件和套接字文件(包含已经建立的连接和监听的连接)。
输出字段解释如下:
字段名 | 含义 | 示例 |
---|---|---|
COMMAND | 打开该文件的进程名 | nginx |
PID | 进程号 | 1234 |
USER | 进程所属用户 | www-data |
FD | 文件描述符编号 + 访问模式 (r/w/u/m ) | 3r 、4w 、mem 、cwd |
TYPE | 文件类型 | REG (普通文件)、DIR 、IPv4 、IPv6 、FIFO 等 |
DEVICE | 设备号(十六进制) | 8,1 表示 /dev/sda1 |
SIZE/OFF | 文件大小 或 偏移量 | 512 或 0t0 |
NODE | inode 号(网络套接字时为协议值) | 12345 |
NAME | 文件/套接字/端口的 实际路径或地址 | /var/log/nginx/access.log 或 TCP *:80 (LISTEN) |
FD列的字段解释
符号 | 中文含义 | 典型场景 |
---|---|---|
cwd | 当前工作目录 | 任何进程启动后都自动带 |
rtd | 根目录(chroot 后) | 容器、Jail |
txt | 程序可执行文件本身 | /sbin/init 、/usr/bin/python3 |
mem | 内存映射文件(已读入内存) | 共享库、大文件 mmap |
mmap | 内存映射设备 | 字符/块设备 |
del | 已删除但仍被占用的文件 | 空间不释放元凶 |
0/1/2 | 标准输入/输出/错误 | 0r /1w /2u |
数字+后缀 | 普通文件描述符 | 3r 只读,7w 只写,9u 读写 |
r表示读,w表示写,w表示读写。
每个进程都有一个文件描述符表,0,1,2都是预定的,假如说后面进程又使用了几个文件描述符的话就从3开始算起。
TYPE列解释
TYPE 缩写 | 全称 / 中文含义 | 常见场景示例 | 快速记忆口诀 |
---|---|---|---|
REG | Regular file(普通磁盘文件) | 被打开的配置、日志、二进制文件 | 普通文件 |
DIR | Directory(目录) | 进程当前目录、被遍历的目录 | 目录本身 |
LNK | Symbolic link(符号链接) | 指向其他文件的软链接 | 链接文件 |
FIFO | FIFO/Named pipe(有名管道) | mkfifo 创建的管道文件 | 管道通信 |
CHR | Character special(字符设备) | /dev/null , /dev/tty , /dev/zero | 字符设备 |
BLK | Block special(块设备) | /dev/sda , 磁盘分区 | 块设备 |
UNIX | UNIX domain socket(本地套接字) | /run/*.sock , X11 socket | 本机套接字 |
IPv4 | IPv4 Internet socket(IPv4 网络套接字) | TCP/UDP 端口监听或连接 | IPv4 网络 |
IPv6 | IPv6 Internet socket(IPv6 网络套接字) | 同上,协议族为 IPv6 | IPv6 网络 |
DEVICE字段解释
device字段一般是用来表示文件的所在位置,一般由两列构成,一列是主驱动类型,一列是具体位置。下面是主驱动类型。
major | 对应驱动 | 常见 minor 举例 | 典型设备节点 |
---|---|---|---|
0 | 虚拟/内存 | 1 → /dev/ram0, 3 → /dev/null, 5 → /dev/zero | /dev/null、/dev/zero |
1 | RAM disk | 0 → /dev/ram0 | 老式 initrd |
7 | loop | 0 → /dev/loop0 | loop 挂载的 ISO |
8 | SCSI/SATA/SD | 0 → /dev/sda, 1 → /dev/sda1 | 普通磁盘分区 |
9 | md | 0 → /dev/md0 | Linux 软 RAID |
11 | sr | 0 → /dev/sr0 | 光驱 |
136-143 | Unix98 PTY | 0 → /dev/pts/0 | 伪终端 |
253 | device-mapper | 0 → /dev/dm-0 | LVM、LUKS |
举例如下:
读 lsof
时怎么用
• 找磁盘文件在哪块盘
$ lsof /var/log/syslog
COMMAND PID USER FD TYPE DEVICE SIZE/OFF NODE NAME
rsyslogd 1234 syslog 20w REG 8,1 102400 131234 /var/log/syslog
DEVICE 8,1 ⇒ /dev/sda1 → 日志落在第一块磁盘第一分区。
问题:有些主设备为0,次设备如何分布的
目前 Linux 内核(Documentation/admin-guide/devices.txt)里已分配的 0 号次设备号分布如下(节选常用节点):
次设备号 | 典型节点 | 功能说明 |
---|---|---|
0 | /dev/cpu/microcode | Intel CPU 微码更新接口 |
1 | /dev/mem | 物理内存直通访问 |
2 | /dev/kmem | 内核虚拟地址空间访问(已废弃) |
3 | /dev/null | 黑洞设备,写入丢弃,读出 EOF |
4 | /dev/port | I/O 端口读写接口 |
5 | /dev/zero | 无限零字节流 |
6 | /dev/core | 兼容旧 core 文件 |
7 | /dev/full | 写时返回 ENOSPC“磁盘满”错误 |
8 | /dev/random | 阻塞随机数池 |
9 | /dev/urandom | 非阻塞随机数池 |
10 | /dev/aio | 异步 I/O 完成通知接口 |
11 | /dev/kmsg | 内核 printk 消息接口 |
12–15 | /dev/pts/ptmx 等 | 伪终端主设备(不同发行版可能变) |
128–135 | /dev/vhci 等 | USB/IP 虚拟主机控制器 |
229 | /dev/fuse | FUSE 用户态文件系统 |
235 | /dev/autofs | autofs 自动挂载守护接口 |
其他 | … | 由内核各子系统动态申请 |
另外,某些tmpfs也是主设备为0的,但是他的次设备号是动态变化的,比如说又是被挂载载/dev/sham,而/dev/sham分配的次设备号是19,那么他的device就是0,19。
inode字段解释
lsof 显示 | 场景 | 含义 |
---|---|---|
十进制数字(如 131234) | 普通磁盘文件、目录、设备节点 | 就是该对象在对应文件系统里的 inode 号 |
0 | 匿名对象 | 例如纯内存映射(mem )、已删除文件(DEL )或某些管道/FIFO,内核不再保留有效 inode 号 |
16 进制数(如 0x1234abcd) | 网络 socket | 代表内核 sockfs 内部的“socket inode 号”,不具备传统文件系统意义 |
name字段解释
打开对象类型 | NAME 典型示例 | 说明 |
---|---|---|
磁盘文件 | /etc/passwd /home/alice/notes.txt | 绝对或相对路径,一眼就知道是哪个文件。 |
已删除但仍占用空间的文件 | /var/log/nginx/access.log (deleted) | 路径后面带 (deleted) ,提示文件已 unlink,但数据块尚未释放。 |
目录 | /home/alice/project | 进程把目录当作文件打开(如 opendir )。 |
字符/块设备 | /dev/null /dev/sda1 | 对应设备节点。 |
管道/FIFO | /tmp/myfifo | 有名管道文件;匿名管道则显示为 pipe 且没有路径。 |
Unix 域套接字 | /run/systemd/private /tmp/.X11-unix/X0 | 文件系统里可见的 socket 文件。 |
IPv4/IPv6 套接字 | localhost:ssh->192.168.1.5:60322 *:http (LISTEN) | 形如 地址:端口 或 *: 表示监听;箭头表示已建立的连接。 |
匿名网络 socket | TCP *:8080 (LISTEN) UDP *:bootpc | 没有本地文件节点,只能看到协议与端口。 |
挂载点/映射文件 | / (path dev=8,1) | 如 cwd、rtd、txt 等记录进程根目录、当前工作目录、可执行文件路径。 |
快速记忆技巧
只要 NAME 以
/
开头,就是文件系统路径;包含
->
的是网络连接;出现
(deleted)
的,重点排查“空间泄漏”;只有协议和端口没有路径的,就是纯网络 socket。
2. lsof的使用场景
lsof
没有“配置文件”意义上的默认参数,它的“默认行为”可以概括为一句话:
不加任何参数时,lsof 会列出
当前调用者(effective UID)
正在打开的所有文件、目录、设备、网络 socket、管道等。
换成人话就是:
等价于
lsof -u $USER
(只显示你权限能看到的进程)。输出列固定为:COMMAND、PID、USER、FD、TYPE、DEVICE、SIZE/OFF、NODE、NAME。
不做端口/主机解析(即
-n -P
的效果)——网络连接直接显示 IP 与数字端口。
常用参数如下:
输出信息的筛选:
-p <PID> | 指定进程号 | lsof -p 1234 |
-u <user> | 指定用户名 | lsof -u alice |
-u ^root | 排除 root(加 ^ 取反) | lsof -u ^root |
-c <cmd> | 命令名模糊匹配 | lsof -c nginx |
-g <GID> | 指定进程组 | lsof -g 1000 |
-i | 所有网络连接 | lsof -i |
-i :80 | 指定端口 | lsof -i :80 |
-i tcp | 指定协议 | lsof -i tcp |
-i @192.168.1.1 | 指定远程地址 | lsof -i @8.8.8.8 |
-U | Unix 域套接字 | lsof -U |
查看文件对象
+d <dir> | 目录下一级打开的文件 | lsof +d /var/log |
+D <dir> | 目录递归(耗时更长) | lsof +D /data |
输出格式
-t | 仅输出 PID(脚本友好) | `lsof -t -i :3306 | |
-n | 不解析主机名 | lsof -n -i | |
-P | 不解析端口号 | lsof -P -i :8080 | |
-l | 显示 UID 而非用户名 | lsof -l -u 1000 |
谁占用了
/opt/data/big.log?
lsof /opt/data/big.log
哪个服务监听 6379?
lsof -i :6379 -sTCP:LISTEN
某目录下被打开的文件 Top10?
lsof +D /data | awk '{print $9}' | sort | uniq -c | sort -nr | head
释放已删除却仍占空间的文件?
lsof | grep deleted