## 报错是什么意思
应用日志里刷出 Too many open files,连接建立失败、文件读写报错,Nginx 还会给出 500 状态。这是每个进程的文件句柄数上限触顶:Linux 给进程能同时打开的文件描述符数量设了默认上限,常见默认值是一千左右,Web 服务、长连接网关、消息队列这类高频读写场景很容易撞上。日志与网络连接在系统眼里都是文件,都要占用句柄额度。Nginx 撞上限时会顺带拒绝新连接,用户侧的表现就是网站时好时坏、图片偶发加载失败。
## 临时与永久修改
临时改只影响当前会话,适合快速验证:
bash ulimit -n 65535
该值只对当前 shell 及其子进程有效,重启即失。
永久改走 limits.conf,在 /etc/security/limits.conf 追加两行:
* soft nofile 65535 * hard nofile 65535
星号对所有用户生效,也可以精确写服务账号。改完重新登录会话生效。systemd 管理的服务有自己的一套,limits.conf 对它无效,要在服务单元里加:
[Service] LimitNOFILE=65535
改完 systemctl daemon-reload 再重启服务。容器场景则在运行参数或 compose 里加 ulimits 段落,层级不同,思路一致。
## 验证方法
改没改到位要看进程的真实值,而不是只看 shell 里的数字。看运行中进程的上限:
bash cat /proc/进程号/limits
输出里 Max open files 一行就是该进程实际生效的软硬限制。看当前已用句柄数用 ls /proc/进程号/fd 统计条目数,已用逼近上限就该继续调大,常态占用超过七成就提前行动,别等报错再动。验证要完整:改配置、重启进程、再查 limits 文件,三步连起来才算数。
## 常见错误
最常见的坑是改了 limits.conf 却用 systemctl 起服务,以为生效实际没变,白查半天。第二是只改软限制不改硬限制,或忘了重新登录。第三是把上限直接拉到百万级别却不看系统全局的 file-max 内核参数,进程上限再高,全局额度先爆也白搭,用 sysctl fs.file-max 核对全局值,不够就一并调。句柄持续增长不回落则不是调参问题,是文件或连接在泄漏,方向应转为查程序。在顺云云服务器上部署高并发服务时,把句柄上限检查纳入上线清单,比事后救火体面。