
本文详解为何 ulimit 和 /etc/security/limits.conf 设置对 supervisor 托管进程无效,并指导通过 minfds 参数在 supervisord.conf 中正确配置最大打开文件数,确保 go 服务(如 http 服务器)稳定运行。
本文详解为何 ulimit 和 /etc/security/limits.conf 设置对 supervisor 托管进程无效,并指导通过 minfds 参数在 supervisord.conf 中正确配置最大打开文件数,确保 go 服务(如 http 服务器)稳定运行。
在 Linux 系统中,提升单个进程的文件描述符(file descriptor)上限是高并发网络服务(尤其是 Go 编写的 HTTP 服务)的常见需求。尽管你已在 /etc/security/limits.conf 中为所有用户设置了 nofile 100000,并验证了当前 shell 的 ulimit -n 输出为 100000,但实际运行中的 Go 进程(PID 1480)仍显示 Max open files: 1024 / 4096 —— 这表明系统级限制并未生效。根本原因在于:Supervisor 并不继承系统的 PAM limits 配置,而是使用自身独立的资源限制机制。
Supervisor 会为其子进程设置默认的文件描述符软硬限制(通常为 1024/4096),且该限制优先级高于 /etc/security/limits.conf。因此,即使你已正确配置系统 limits,只要未显式配置 Supervisor,其托管的 Go 程序仍将受限于 Supervisor 的默认值,从而触发 accept4: too many open files 或 open /dev/null: too many open files 等典型错误。
✅ 正确解决方案:在 Supervisor 的主配置文件 /etc/supervisor/supervisord.conf(而非程序级配置如 /etc/supervisor/conf.d/myapp.conf)中设置 minfds:
# 编辑 /etc/supervisor/supervisord.conf [supervisord] minfds = 100000
⚠️ 注意事项:
- minfds 必须置于 [supervisord] 全局节下,不能写在 [program:mygoapp] 节中,否则无效;
- 修改后需重启 supervisord 主进程(非仅 reload)才能生效:
sudo systemctl restart supervisor # 或 sudo service supervisor restart
- 验证是否生效:获取目标 Go 进程 PID 后,检查 /proc/<PID>/limits:
cat /proc/$(pgrep -f "your-go-binary")/limits | grep "Max open files" # 正确输出应为: # Max open files 100000 100000 files
此外,建议同步校验以下三点以排除其他干扰:
- 确保 /etc/security/limits.conf 中的配置无语法错误(每行末尾无空格,域名为 * 或具体用户名);
- 若使用 systemd 启动 supervisord,请确认 LimitNOFILE 未被 systemd 单元文件覆盖(可检查 /lib/systemd/system/supervisor.service);
- Go 程序自身无需额外调用 syscall.Setrlimit,只要进程启动时环境已满足要求,标准库(如 net/http)即可正常分配 socket。
总结:Supervisor 是一个“资源守门人”,它不会自动透传系统 limits。要真正解除文件描述符瓶颈,必须在 supervisord.conf 中显式声明 minfds,这是面向生产环境部署 Go 微服务的关键运维实践。


















