limits.conf配置不生效的根本原因是pam的pam_limits.so模块未加载,仅对login shell生效;常见失效场景包括su oracle(不带-)、systemd服务绕过pam、/etc/pam.d/{login,sshd}缺失session required pam_limits.so行,且必须成对配置soft/hard nofile、精确匹配用户名、rac节点逐个验证。

改了 /etc/security/limits.conf 但 Oracle 启动失败或 ulimit -n 显示值没变?大概率不是配置写错了,而是 PAM 根本没生效——Oracle 进程压根没走 pam_limits.so 这条链。
为什么 limits.conf 配置不生效
根本原因:PAM 的 pam_limits.so 模块只对经过完整 PAM 认证的 login shell 会话起作用。而以下常见场景都绕过了它:
-
su oracle(不带-)启动的 shell 不是 login shell,不会读/etc/security/limits.conf - systemd 管理的 Oracle 服务(如
oracle-db.service)默认不调用 PAM,limits.conf完全被忽略 -
/etc/pam.d/login或/etc/pam.d/sshd中缺失session required pam_limits.so行 - Oracle 用户用非交互式方式(如 cron、脚本直接调用
sqlplus)启动进程,也不会触发 session 模块
必须配全的三要素
单写 limits.conf 不够,三个位置必须同时确认:
-
/etc/security/limits.conf:必须成对写 soft/hard,且精确匹配用户名oracle soft nofile 65536oracle hard nofile 65536oracle soft nproc 16384oracle hard nproc 16384 -
/etc/pam.d/login(或/etc/pam.d/sshd):确保含这一行session required pam_limits.so -
登录方式:必须用 login shell 登录,即
su - oracle或 SSH 直连,不能用su oracle
漏掉任意一项,ulimit -n 就可能还是 1024。
systemd 环境下必须显式设置 LimitNOFILE
如果 Oracle 是通过 systemctl start oracle-db 启动的(RPM 安装或云上部署常见),limits.conf 生效不了。必须在 service 文件里硬编码:
[Service] LimitNOFILE=65536 LimitNPROC=16384
注意:LimitNOFILE 是 systemd 的原生命令,不是环境变量;它优先级高于 PAM,且不依赖 login shell。
验证方式不是看当前终端的 ulimit,而是查 Oracle 进程本身:
先找 ora_pmon_<sid></sid> PID:ps -u oracle -o pid,comm | grep pmon
再查限制:cat /proc/<pid>/limits | grep "Max open files"</pid> —— 必须显示两个 65536 才算真正落地。
容易被忽略的内核上限和数值截断
即使 PAM 和 systemd 都配对了,数值也可能被静默砍掉:
- 检查系统级上限:
cat /proc/sys/fs/nr_open,若设的65536超过它,实际生效值就是nr_open值 - Oracle 19c+ 会主动尝试把
nofile提升到 hard limit,所以 soft 和 hard 必须一致,否则可能因提升失败报ORA-27123 - 不要用
*替代用户名,pam_limits.so对oracle是精确字符串匹配,*只匹配非 root 普通用户,不包括 oracle
最危险的盲区:RAC 环境中,每个节点都要单独验证 /proc/<pid>/limits</pid>,一个节点漏配,整个集群就可能因共享内存 attach 失败而无法启动。











