首页/系统/Linux 运维命令速查/lsof 直查进程句柄问题

lsof 直查进程句柄问题

服务报 Too many open files、文件消失、端口占用:lsof 按进程/文件列出句柄,与 ulimit 搭配定位句柄泄漏与配置错位。

Linux 运维命令速查系统更新于 2026-10-13

这条路径解决什么

服务报 Too many open files、磁盘明明有空间却写入失败、文件删了空间不释放,这些问题的共同点是「进程持有的句柄」。lsof 按进程或文件列出当前打开的文件描述符,配合 /proc/PID/limits 与 /proc/PID/fd 就能判断是上限设小了,还是程序自己在泄漏句柄。

基本信息

适用场景句柄不足、句柄泄漏、删除文件空间不释放
核心工具lsof 列表、/proc/PID/limits 看上限、/proc/PID/fd 数句柄
常用组合lsof -p PID、lsof +L1 找已删除但仍被持有的文件
判据句柄数接近上限即为瓶颈;数量随时间持续增长即为泄漏
权限说明查看其它用户的进程需要 root

典型使用场景

  • 报 Too many open files:确认当前句柄数与实际上限,找出是谁在开文件
  • 句柄泄漏排查:按时间多次采样数量,判断是否持续增长
  • 空间不释放:文件已删但进程仍持有,用 lsof +L1 定位
  • 配置核对:确认服务进程真正生效的 nofile 上限
  • 发布前排雷:确认新版本没有打开大量连接或文件

常用示例

常用示例
lsof -p 1234 | wc -l                              # 该进程当前句柄数
lsof -p 1234 | awk '{print $5}' | sort | uniq -c | sort -rn | head   # 按类型统计
cat /proc/1234/limits | grep -i 'open files'       # 实际上限(软限与硬限)
ls /proc/1234/fd | wc -l                           # 更快的句柄计数
lsof +L1 2>/dev/null | grep -i app                 # 已删除但仍被打开的日志
lsof -u www-data | wc -l                           # 按用户统计总量

观察趋势

观察趋势
while true; do
  printf '%s %s\n' "$(date +%T)" "$(ls /proc/1234/fd | wc -l)"
  sleep 60
done

句柄上限的三种来源

来源作用范围查看方式
ulimit -n当前 shell 及其子进程在对应会话里执行 ulimit -Hn 与 -Sn
/etc/security/limits.conf经 PAM 登录的会话grep 用户名 与 nofile 行
单元里的 LimitNOFILE该 systemd 服务systemctl show 服务名 -p LimitNOFILE
systemd 全局 DefaultLimitNOFILE未被单独指定的服务grep 系统级 systemd 配置
容器运行时限额容器内进程docker inspect 或编排文件里的 ulimit 配置
Too many open files 要三处一起查:会话侧的 ulimit -n、登录策略的 limits.conf、服务单元里的 LimitNOFILE。systemd 服务只看单元或全局默认值,完全不读 limits.conf,这是「配置了却不生效」的典型原因。另外 lsof 的结果受权限限制:看不到其它用户进程的句柄时,用 sudo 重跑再统计,否则数量会被低估。
排查句柄泄漏的关键是趋势而不是瞬时值:定时采样 /proc/PID/fd 的数量并记录,只有在业务量稳定时数量仍持续上升,才能认定为泄漏。瞬时的峰值可能只是并发连接波动,不必急于改上限。另外句柄需求与并发模型强相关:Nginx、Java 这类进程常常一个连接占一个描述符,评估上限要按峰值连接数留出余量。

易错点

  • limits.conf 对 systemd 服务不生效:服务走单元文件 LimitNOFILE 或全局 DefaultLimitNOFILE
  • 句柄计数包含管道、套接字与匿名 inode,只看普通文件会低估总量
  • 判断泄漏要看趋势:单次采样偏高可能只是并发峰值
  • 文件删除后空间不释放,要查是否仍有进程持有该 inode,而不是反复删除
  • /proc/PID/limits 显示的才是进程真正生效的上限,配置文件里写的不一定是最终值

数据来源与参考

  • man 8 lsof
  • man 5 limits.conf

相关工具

​‌‌​​‌​​​‌‌​‌‌‌‌​‌‌​​​‌‌​‌‌‌​​‌‌​​‌​‌‌‌​​‌‌‌​​​‌​‌‌​‌​​‌​‌‌‌​​​‌​‌‌​‌​​‌​‌‌​​​‌‌​‌‌‌​‌​​​‌‌​‌‌‌‌​​‌​‌‌‌​​‌‌​​​‌‌​‌‌​‌‌‌‌​‌‌​‌‌​‌