Manjaro/Arch 彻底解决 "Too many open files":为什么你改的 limits.conf 不生效

问题现场

当你训练模型、处理大量文件或运行高并发服务时,突然出现:

Failed creating file: ... [Too many open files]

你按照标准方案修改了 /etc/security/limits.conf

* soft nofile 65536
* hard nofile 65536

但重启后 ulimit -n 依然显示 10244096。为什么?

根本原因:Systemd 接管了资源限制

Manjaro(及 Arch 等现代 Linux 发行版)使用 Systemd 作为核心进程管理器。关键事实:

Systemd 管理的进程(包括用户桌面会话)在启动时会忽略传统的 limits.conf 配置!
它们只认 Systemd 自己的资源限制设置。

完整解决方案(四步走)

1. 修改系统级服务限制

sudo nano /etc/systemd/system.conf

取消注释并修改:

DefaultLimitNOFILE=65536:65536  # 格式:soft:hard

2. 修改用户级服务限制(关键!常被遗漏)

sudo nano /etc/systemd/user.conf

同样取消注释并修改:

DefaultLimitNOFILE=65536:65536

3. 重载配置并重启

# 重载系统配置
sudo systemctl daemon-reload

# 重载用户配置(必须执行!)
systemctl --user daemon-reload

# 彻底重启(否则不生效)
reboot

4. 验证生效情况

# 查看当前shell限制
ulimit -n  # 应输出65536

# 检查任意进程的实际限制
sleep 1h &  # 启动测试进程
cat /proc/$!/limits | grep "Max open files"

输出应包含:

Max open files            65536                65536                files

常见问题排查

1. 为什么桌面应用仍受限?

  • 原因:图形应用由 systemd --user 管理,只受 user.conf 约束
  • 解决:确保修改了 user.conf 并执行 systemctl --user daemon-reload

2. 重启后部分终端仍显示旧限制

  • 原因:终端会话未完全重启
  • 解决:关闭所有终端窗口,重新打开新终端

3. 系统服务(如Docker)未生效

  • 原因:系统服务受 system.conf 约束
  • 解决:确认已修改 system.conf 并执行 sudo systemctl daemon-reload

高级场景处理

只为特定服务增加限制

# 创建服务覆盖配置
sudo systemctl edit nginx.service

# 添加内容
[Service]
LimitNOFILE=1048576

临时调试解决方案

# 当前终端会话有效
ulimit -n 65536

# 修改运行中进程的限制
prlimit --pid <PID> --nofile=65536:65536

为什么 limits.conf 会失效?

  • limits.conf 依赖 PAM 认证流程生效
  • Systemd 管理的进程(特别是桌面环境)绕过 PAM 初始化
  • 用户级服务由 systemd --user 直接启动,继承其默认限制

配置作用域总结

配置文件 影响范围 典型场景
/etc/systemd/system.conf 系统级服务 Docker, Nginx, PostgreSQL
/etc/systemd/user.conf 用户级进程 桌面应用,终端启动的脚本
/etc/security/limits.conf 通过PAM登录的会话 SSH登录,tty控制台

终极验证命令

# 查看系统全局限制
cat /proc/sys/fs/file-max

# 查看当前用户限制
ulimit -n

# 查看具体进程限制
cat /proc/$(pgrep -f your_process)/limits | grep open.files

# 查看已打开文件数
lsof -u $USER | wc -l

总结流程图

graph LR A[遇到错误] --> B{进程类型} B -->|系统服务| C[修改 system.conf] B -->|用户进程| D[修改 user.conf] C --> E[执行双 reload] D --> E E --> F[重启系统] F --> G[验证结果] G -->|仍受限| H[检查特定服务]
posted @ 2025-06-01 22:46  M4K0  阅读(69)  评论(0)    收藏  举报