最稳妥的限制方式是将服务账户 shell 设为 /sbin/nologin 或 /usr/sbin/nologin,它不删用户、不改密码、不影响 cron/systemd 服务,仅阻止交互式登录并支持自定义提示;需先验证路径存在,再用 usermod -s 安全修改,最后通过 getent passwd 验证第七列生效。

usermod -L 和 /sbin/nologin 是两类不同机制,选错会导致禁用失效或绕过——必须先明确你要阻断的是“密码认证”还是“所有交互式登录”。
用 usermod -L 锁定密码,但 SSH 密钥仍可能登录
这个操作只改 /etc/shadow,在密码哈希前加 !!,让系统拒绝任何基于密码的验证:
• 无法用密码 SSH、su、console 登录
• 不影响已配置的 SSH 公钥登录(只要 AuthorizedKeysCommand 或 PubkeyAuthentication yes 仍启用)
• 不影响 root 执行 su - username(因为不校验目标用户密码)
• 验证方式:运行 passwd -S username,第二列显示 LK;或 getent shadow username | cut -d: -f2 输出以 !! 开头
• 解锁必须用 usermod -U username 或 passwd -u username,pam_tally2 --reset 对它完全无效
用 usermod -s /sbin/nologin 彻底禁用交互式 shell
这是真正“不让进 shell”的做法,发生在认证之后、会话启动之前,比锁密码更彻底:
• 所有交互式登录(SSH 密码、SSH 密钥、console、su)全部被拦截并退出
• 仍可执行 sudo -u username command、cron、systemd --user 服务(只要不是交互式调用)
• 路径必须准确:/sbin/nologin(RHEL/CentOS 7、旧 Debian)或 /usr/sbin/nologin(Ubuntu 22.04+、RHEL 8+);ls -l /sbin/nologin /usr/sbin/nologin 2>/dev/null 查哪个存在
• 可自定义提示:写入 /etc/nologin.txt(仅 nologin 读取,/bin/false 不支持)
• 恢复只需 usermod -s /bin/bash username,无需动密码或 PAM
别混用 chage -E 0 和 shell 修改,它们解决的问题完全不同
chage -E 0 username 是账户过期机制,本质是时间策略:
• 立即生效,但只对需要检查账户有效期的认证模块起作用(如 PAM 的 pam_time 或某些 LDAP 集成)
• 某些 SSH 配置下可能被忽略,不如 usermod -L 或 nologin 可靠
• 它和 shell 修改互不干扰:一个用户可以同时是 chage -E 0 + /sbin/nologin,但没必要——后者已足够干净
• 如果你只是临时停用某人(比如员工休假两周),chage -E 配合 -M 设置最大密码年龄更合适;长期禁用请直接走 nologin
最容易被忽略的绕过点:ForceCommand 和 AuthorizedKeysCommand
即使设了 /sbin/nologin,如果用户 SSH 配置了 ForceCommand 或全局启用了 AuthorizedKeysCommand,仍可能执行命令而不经过 shell 启动流程:
• 检查 /etc/ssh/sshd_config 是否含 ForceCommand 或 AuthorizedKeysCommand
• 检查用户 ~/.ssh/authorized_keys 中是否带 command="..." 选项
• 这类绕过不会触发 /etc/nologin.txt 提示,也看不到登录失败日志——它根本没走到 shell 启动那步
• 真正要杜绝所有远程命令执行,得配合 SSH 的 AllowUsers 或 Match User 规则做白名单控制











