为什么总提示“打开文件过多”,还伴随僵尸进程?
用 ss 和 lsof 找出泄漏文件描述符的进程,再用 ulimit 提高上限,并让配置在重新登录后依然生效。
快速开始
“Too many open files” 和僵尸进程往往同时出现,因为根源常常是同一个不听话的服务:它只打开文件描述符却不关闭,只创建子进程却不回收。也正因为如此,单纯把上限调高只能拖延故障。本指南从定位作乱进程开始,接着调高上限,最后把配置固化下来,让它在下次登录或重启后依然有效。
症状
先看清是哪个进程占着大量 socket
不要凭感觉调参数,先数一数。这个视图会把所有监听中和已建立的 TCP/UDP 连接连同所属进程一起列出来,如果某个服务挂着几百条连接,一眼就能看出来。这种形态通常说明是单个程序在泄漏文件描述符,而不是整台机器的上限不够用。这一步做完,你应该能说出占用最多的那个进程名字,并记下它的 PID。
用“已删除但仍被打开的文件”确认泄漏
如果程序打开文件、删除它,却从不关闭,这个描述符就会一直存在 — 这类文件在列表里的链接数为 0。若同一个 PID 反复出现,说明问题确实是泄漏,而不是上限设得太小,此时单纯调高上限只会把崩溃时间往后推。查看别人的描述符需要 root 权限,所以会提示输入密码,这是正常的。
当 df 显示磁盘满但 du 却找不到大文件时,多半是有进程还握着已删除的文件;lsof +L1 能把它们和占用进程一起列出来。
$ sudo lsof +L1在启动服务的那个 shell 里调高描述符上限
进程的上限是从 fork 它的 shell 继承来的,所以必须在服务启动之前、在同一个 shell 里修改。用那个既能查看又能设置上限的 shell 内置命令,把数值调大,之后从该 shell 启动的程序就不会再立刻报“打开文件过多”。设置完在同一个会话里再打印一次确认,数值变大了就说明生效;退出登录后这个改动会丢失。
ulimit -n 可查看或修改当前 shell 的文件描述符上限,解决从该 shell 启动的服务报“Too many open files”的问题。
$ ulimit -n 4096▾ 撤销
$ ulimit -n 1024让新上限在重新登录后依然有效
刚设置的数值只活在当前 shell 里。就地编辑 PAM 的 limits 配置文件,可以让每个新登录会话都拿到更高的上限,服务器上一般都需要这样做。由于就地编辑会直接写盘,先留一份备份,免得写错语法之后连自己都登不进去。验证方式是另开一个全新会话,在里面打印上限,看到的数字应该是调大后的值;另外别忘了,已经在跑的服务必须重启才会继承新上限。
用 sed -i 在 Linux 上对单个或多个文件做查找替换,配合 -i.bak 保留备份。
$ sed -i 's/old-domain.com/new-domain.com/g' *.conf▾ 撤销
$ git checkout -- *.conf (or restore from the .bak created by sed -i.bak)如何确认已解决
改动之后再跑一次 socket 列表,盯住那个作乱进程:连接数停在新上限之下且不再持续上涨。新开的登录会话显示的是调大后的数值,日志里不再出现新报错,父进程重启后僵尸条目也随之消失。
一键全部撤销
上面每一条命令都可以撤销。按此顺序执行即可全部还原。
$ git checkout -- *.conf (or restore from the .bak created by sed -i.bak)
ulimit -n 1024执行前请先确认——部分步骤之间可能并非相互独立。
来源
- lsof(8) - Linux manual page依据: The +L1 option selects files with a link count less than one, i.e. open files that have been unlinked (deleted).
- Sed — ArchWiki依据: Examples of GNU sed -i in-place editing and -i.bak backup extension usage
- getrlimit(2)/setrlimit(2) - get/set resource limits依据: RLIMIT_NOFILE specifies a value one greater than the maximum file descriptor number that can be opened by this process; limits have a soft value (enforced) and a hard value (ceiling for the soft).
- ss(8) — Arch Manual Pages依据: Same options documented for ss, another utility to investigate sockets.
- ss(8) — Debian bookworm依据: Documents -t/--tcp, -u/--udp, -l/--listening, -p/--processes and -n/--numeric for the socket statistics tool.
- sed(1P) — POSIX manual page依据: Documents the s/re/replacement/flags substitution, /g global flag, and address ranges
最后验证: 2026-09-22