/etc/security/limits.conf 不生效的主因是未启用 pam limits 模块或服务未走 login session 流程;systemd 服务需在 unit 文件中显式配置 limitnofile,ssh 需确保 /etc/pam.d/sshd 含 session required pam_limits.so,图形界面则依赖显示管理器配置或 systemd user/system.conf。
linux 系统中 /etc/security/limits.conf 不生效的常见原因
直接改了 /etc/security/limits.conf 却发现 ulimit -n 还是老样子?大概率是没启用 pam limits 模块,或者服务没走 login session 流程。
- systemd 服务默认不读
limits.conf,得在 service 文件里显式加LimitNOFILE=65536等字段 - SSH 登录需确认
/etc/pam.d/sshd包含session required pam_limits.so - 图形界面(如 GDM、SDDM)往往绕过 PAM limits,得查对应显示管理器文档,或改
/etc/systemd/user.conf和/etc/systemd/system.conf中的DefaultLimitNOFILE - 用户登录后新开的 shell(比如终端里再 bash)继承的是父进程限制,不是重新读配置 —— 必须登出重进或用
su - $USER触发新 session
密码策略配置:/etc/pam.d/common-password 里的关键控制项
Ubuntu/Debian 系统改密码强度,核心在 common-password,而不是 /etc/login.defs —— 后者只管新建用户的默认值,不干预校验逻辑。
-
pam_pwquality.so(旧版叫pam_cracklib.so)才是执行长度、复杂度、历史记录检查的模块 - 常用参数:
retry=3(输错三次才拒绝)、minlen=12(最小长度)、lcredit=-1 ucredit=-1 dcredit=-1 ocredit=-1(至少含大小写字母、数字、特殊字符各一个) - 注意顺序:同一行多个
pam_pwquality.so实例会叠加生效;若已有required行,新加的得设成sufficient或调整顺序,否则可能被跳过 - 改完立刻生效,但只对后续
passwd命令起作用,不影响已存在的弱密码账户
如何让非交互式环境(如 cron、systemd timer)也应用用户级 limits
cron 任务和 systemd timer 默认以 minimal environment 运行,完全不加载 limits.conf 或 shell profile,所以 ulimit 总是系统默认值。
- cron:在 crontab 条目开头手动加
ulimit -n 65536;,或封装成脚本并在脚本第一行写#!/bin/bash -l(带 login flag 才读 profile) - systemd timer:必须在对应 .service 文件里配资源限制,例如
LimitNOFILE=65536、MemoryLimit=512M;不能指望~/.bashrc或/etc/profile - 注意:systemd 的
Limit*配置只作用于该 unit 的主进程及其直系子进程,fork 出来的后台进程若 daemonize,可能脱离 cgroup 控制 —— 得配合Delegate=yes和TasksMax=细粒度约束
profile 文件加载顺序混乱导致设置被覆盖
用户登录时,/etc/profile、/etc/profile.d/*.sh、~/.profile、~/.bashrc 的执行顺序和条件很关键,一处写错就白配。
- login shell(SSH、tty)读
/etc/profile → /etc/profile.d/*.sh → ~/.profile;non-login shell(终端点开的新 tab)只读~/.bashrc -
~/.bashrc开头常有[ -n "$PS1" ] || return,导致 sourced 时提前退出 —— 若你用source ~/.bashrc测试,它根本不会执行后面 ulimit 设置 - 避免在
~/.bashrc里重复设ulimit,因为 PAM limits 已在 session 层搞定;这里只该放 shell 别名、PATH 等交互增强项 - 想全局生效又不想改每个用户家目录?优先动
/etc/profile.d/下的新 .sh 文件,比改/etc/profile更安全、更易维护
真正麻烦的不是配哪一行,而是搞清哪个组件在哪个环节读哪份配置。PAM、systemd、shell、display manager 各自有一套规则,混在一起就容易漏掉某一层 —— 动手前先用 loginctl show-user $USER 或 systemctl --user show 看实际生效的 limits 值,比盲调快得多。










