最准方式是读 /proc/pid/limits:max open files 后两数分别为 soft 和 hard 限制;ulimit -n 仅显示当前 shell 会话限制,不反映子进程真实值;/etc/security/limits.conf 仅对 pam 登录会话生效;systemd 服务需用 limitnofile 在 override.conf 中配置。

查看进程当前打开的文件句柄数和软硬限制
直接看某个进程(比如 PID 1234)实际用了多少句柄、上限是多少,最准的方式是读 /proc/1234/limits:
cat /proc/1234/limits | grep "Max open files"输出类似
Max open files 1024 4096 files,左边是 soft limit(软限制),右边是 hard limit(硬限制)。注意:soft 可在运行时调小或调大(不超过 hard),hard 只能 root 降级或在启动前设高。为什么 ulimit -n 查不到子进程的真实限制?
ulimit -n 只显示当前 shell 会话的限制,不是目标进程的。如果进程是 systemd 启动的,它根本不受 shell 的 ulimit 影响;如果是 daemon 化进程(如 nginx、redis),往往由 init 系统接管,其 limits 来自服务单元配置或系统默认值。常见错误是改了 ~/.bashrc 里的 ulimit,却对后台服务完全无效。
修改 /etc/security/limits.conf 的关键写法和生效条件
这个文件只对 PAM 登录会话生效(比如 ssh 登录、console login),不作用于 systemd 服务、cron 或直接 nohup 启动的进程。正确写法示例:
* soft nofile 65536<br>* hard nofile 65536<br>nginx soft nofile 1048576<br>nginx hard nofile 1048576注意:
• 第一列可以是用户名、
@组名 或通配符 *(表示所有用户,但不含 root,root 需单独写)• 必须同时设置
soft 和 hard,否则 soft 不会自动继承 hard 值• 修改后需重新登录(或新开 ssh 连接),旧会话不刷新
• 某些发行版(如 Ubuntu 22.04+)默认禁用 limits.conf,需确认
/etc/pam.d/common-session 中有这一行:session required pam_limits.sosystemd 服务绕过 limits.conf 的正确改法
对于 systemctl start nginx 这类服务,limits.conf 完全不生效。必须改服务单元文件:
sudo systemctl edit nginx然后写:
[Service]<br>LimitNOFILE=1048576保存后重载并重启:
sudo systemctl daemon-reload<br>sudo systemctl restart nginx注意:
•
LimitNOFILE 是 systemd 原生参数,等价于 ulimit -n,但优先级更高• 不要写在
/usr/lib/systemd/system/nginx.service 里(会被包管理器覆盖),用 systemctl edit 写到 /etc/systemd/system/nginx.service.d/override.conf• 如果服务是用户级(
systemctl --user),则需在 ~/.config/systemd/user.conf 中设 DefaultLimitNOFILE=真正容易被忽略的是:同一个进程可能受多层限制叠加影响——PAM session、systemd unit、启动脚本里的 ulimit、甚至程序自身调用 setrlimit()。查问题时,第一反应不该是“我改了 limits.conf 为啥没用”,而是先 cat /proc/PID/limits 看真实值,再反推哪一层出了偏差。











