改了/etc/security/limits.conf仍报“too many open files”,最常见原因是pam未加载limits模块,需检查/etc/pam.d/sshd或login是否含session required pam_limits.so;oracle用户须重新完整登录(非su),且systemd服务需在unit文件中配置limitnofile。
为什么改了 /etc/security/limits.conf 还是报 too many open files
直接改完 limits.conf 不生效,最常见原因是没触发 pam 限制加载——这个文件本身不自动生效,得靠登录会话被 pam_limits.so 拦截并应用。如果用户是通过 ssh 长连接、systemd user session、或者容器内启动的 oracle 进程,很可能根本没走这层认证流程。
验证是否加载:检查 /etc/pam.d/sshd(SSH 登录)或 /etc/pam.d/login 是否包含 session required pam_limits.so。缺这一行,limits.conf 就是摆设。
容易踩的坑:
• root 用户在某些发行版(如 RHEL 8+/CentOS 8+)默认使用 systemd-logind 管理会话,limits.conf 对 root 的全局配置可能被 /etc/systemd/system.conf 中的 DefaultLimitNOFILE= 覆盖;
• Oracle 安装或 dbstart 脚本若由 root 启动再 su - oracle,中间 shell 可能未重载 limits;
• 使用 su oracle(不带 -)不会启动新 login shell,limits.conf 不生效。
nofile 值设多大才安全?别碰 nr_open 上限
Oracle 官方建议单实例至少 65536,但实际要留余量。设太高反而危险:Linux 内核用 /proc/sys/fs/nr_open 控制单进程最大可打开句柄数,默认值通常是 1048576(100 万)。如果在 limits.conf 里写 * hard nofile 2000000,而 nr_open 还是默认值,系统会在用户登录时拒绝认证,出现 Permission denied 或直接黑屏。
必须按顺序操作:
• 先查当前上限:cat /proc/sys/fs/nr_open;
• 若需设 >1048576,先改 /etc/sysctl.conf 加 fs.nr_open = 2097152,再执行 sysctl -p;
• 再去改 limits.conf,且 hard nofile 不能超过刚设的 nr_open 值;
• soft 值必须 ≤ hard,否则以 hard 为准,且 soft 才是运行时实际生效值。
Oracle 用户专用配置怎么写才不被覆盖
别只写 * 全局通配——Oracle 进程常以 oracle 用户身份运行,但系统服务(如 oraagent)或监听器(tnslsnr)可能由 grid 或其他用户启动。必须显式指定:
oracle soft nofile 65536oracle hard nofile 65536grid soft nofile 65536grid hard nofile 65536
注意:
• 不要用 - nofile 语法(等价于同时设 soft/hard),某些老版本 PAM 解析异常;
• 行末不要加空格或注释,PAM 解析器很脆弱;
• 修改后必须让 oracle 用户**完全退出所有 shell 并重新登录**(不是 su - oracle),否则旧会话仍用旧 limit;
• 验证是否生效:登录后立即执行 ulimit -n,应输出 65536;再用 ps -eo pid,user,cmd | grep pmon 找到 Oracle 进程 PID,然后 cat /proc/<pid>/limits | grep "Max open files"</pid> 看内核级确认值。
systemd 环境下 Oracle 服务启动时 limits 丢失怎么办
如果你用 systemctl start oracle-db 启动数据库,那 limits.conf 几乎肯定无效——systemd 服务绕过了 PAM,它读的是自己的资源配置。此时必须在 service unit 文件里硬编码:
编辑 /etc/systemd/system/oracle-db.service,在 [Service] 段下加:
LimitNOFILE=65536 LimitNPROC=16384
然后执行:
• systemctl daemon-reload;
• systemctl restart oracle-db;
• 再用 cat /proc/<pid>/limits</pid> 检查是否已更新。
关键点:
• LimitNOFILE 是 systemd 的原生命令,优先级高于 limits.conf;
• 如果 Oracle 是通过 dbstart 脚本调用的,脚本本身也要在开头加 ulimit -n 65536,否则子进程继承父 shell 的默认 1024;
• 别忘了同步调整 file-max(系统级总上限):echo 'fs.file-max = 2097152' >> /etc/sysctl.conf && sysctl -p。











