ARTICLE · INTELLIGENCE

战地情报 · 详情页

来自尧图项目组的一线实战观察与深度解析

修改root密码的完整指南:passwd命令、PAM联动与常见坑位排查

修改root密码的完整指南:passwd命令、PAM联动与常见坑位排查

改个 root 密码,在很多老运维眼里小到不值一提,但我去过不少项目组救火,发现越是觉得简单的事,翻车的概率反而越高。有一次某位同事在业务服务器上执行完passwd一切正常,结果第二天新密码死活登不进去,最后排查出来是 PAM 模块和密码策略的联动问题。也有一次我在测试环境里用单用户模式重置密码,忘记重新设置 SELinux 上下文,重启后登录直接失败。所以先下个结论:修改 root 密码本身确实只要一条命令,但读懂为什么改、在什么环境改、改完要联动检查哪些东西,才是这事的完整面。

这篇内容主要面向两类人:一类是刚接触服务器管理的读者,需要把修改 root 密码的正确姿势一次吃透;另一类是已经踩过坑的运维朋友,可以对照排查清单看看自己是不是漏了某个联动环节。我会把不同场景下的修改路径、背后的机制原理、以及真实环境里遇到过的故障都整理出来,希望能让你少走几趟弯路。

1. 修改root密码前,先把这三件事想清楚

1.1 你的环境里到底谁是管理员

很多教程张口就是"修改 root 密码",但实际环境差异很大。在传统的 CentOS、Rocky Linux、AlmaLinux 里,root 是默认存在的超级用户,安装系统时你设置的密码就是 root 密码。而在 Ubuntu、Debian 系发行版,默认安装完成后 root 处于锁定状态,日常管理靠的是sudo提权。也就是说,你平时用的用户虽然有管理员权限,但 root 本身并没有可登录的密码。

这里有个容易混淆的操作:在 Ubuntu 上执行sudo passwd root,本质是"给 root 设置一个新密码,并解锁 root 账号",这和在 CentOS 上passwd root的语义完全不同。如果你不清楚自己的系统属于哪种模式,改完之后可能会出现"明明设置了密码却无法用 root 登录"或者"原本能 sudo 的用户突然提权失败"这类问题。

判断方法很直接:执行cat /etc/os-release看发行版,再执行passwd -S root查询 root 账号状态。输出里L表示锁定,P表示有可用密码,NP表示无密码。确认清楚状态再动手,是第一步。

1.2 你将从哪个入口执行操作

修改 root 密码的入口直接决定了操作风险。如果你在服务器本机终端操作,即使中途断开,物理键盘还在机房里,重新登录即可。但如果你是通过 SSH 远程连接,改密码这件事就变得有风险了——不是怕命令执行失败,而是怕过程中网络抖动导致连接中断。

我在生产环境处理过一次比较典型的案例:某位开发者通过 SSH 远程执行passwd root,输完老密码后网络闪断,SSH 会话直接掉线。此时新密码已经写入了一半,旧密码失效,新密码不完整,他彻底进不了系统。最后只能联系机房走带外管理口(比如 IPMI、iLO),或者通过云厂商的控制台 VNC 进入,折腾了将近一个小时。

所以,远程修改 root 密码之前,先确认有没有第二重保障:物理终端、带外管理卡、云厂商的 VNC/救援模式,至少占一个。如果都没有,建议谨慎操作,最好选在业务低峰期,并且提前把sshd配置为"密码修改后允许已建立的连接保持",这个细节后面会讲到。

1.3 密码策略与账号状态,容易被忽略的暗坑

修改密码不是"改完就算完事",系统里还有一套完整的密码策略机制在约束你。常见的有:

  • 密码最小长度、复杂度要求,由/etc/pam.d/system-auth配合pam_pwquality.so控制
  • 密码最大有效期、到期前警告天数,由/etc/login.defs和chage命令控制
  • 密码历史记录,防止复用近期密码,由pam_pwhistory.so控制

我曾经在一台 RHEL 系的服务器上遇到过这样的情况:明明设置了新密码,系统也提示成功,但下次登录时依然要求改密码,改完还是被拒。排查后发现是/etc/shadow里的密码过期字段被之前的脚本改过,chage -M设置了 0 天,新密码立刻过期,然后 PAM 又强制要求再次修改,死循环。处理方式是把过期天数改回来,或者用chage -l root查看详细状态。

还有一个冷门但极致的坑:有人为了防止 root 密码被恶意篡改,用chattr +i /etc/shadow给密码文件加了不可修改属性。这种情况下你执行passwd会提示"无法修改密码",但日志里看不出任何异常。遇到这种报错,先检查文件属性,用lsattr /etc/shadow看一眼,有i标记就先用chattr -i解除。

2. 三种常用修改路径与适用场景

2.1 能正常登录:passwd 命令修改

最常规的场景是你能通过 root 账号或 sudo 权限正常登录系统。此时修改密码的完整命令是这样的:

# 已在 root 用户下,直接修改 passwd # 或者在普通用户下,通过 sudo 修改 root 密码 sudo passwd root

执行后系统会依次要求输入当前密码(root 用户改自己时)、新密码、再次确认新密码。成功后会输出类似passwd: all authentication tokens updated successfully的提示。

注意passwd默认不会显示输入字符,这是终端安全机制,不是卡住了,正常盲打即可。如果你需要脚本化修改密码,可以用chpasswd或echo "root:新密码" | chpasswd,但这种方式会留下 shell 历史记录或进程列表暴露密码,不建议用在真实环境。更安全的做法是通过管道从文件读取。

修改完成后,最好开一个新的终端会话,用新密码测试登录一次,确认成功后再关掉旧会话。这在远程管理时是黄金法则——永远不要在没验证新密码的情况下关闭当前可用连接。

2.2 忘记密码:单用户模式重置

忘记密码是另一个高频场景。此时无法正常登录系统,需要重启进入单用户模式,或者在某些系统里叫"救援模式"。单用户模式会以最小化环境启动,挂载根文件系统为只读,你需要把它重新挂载为可写,才能修改/etc/shadow里的密码字段。

以较常见的 RHEL/CentOS/Rocky 系统为例,步骤如下:

  1. 重启服务器,在 GRUB 菜单出现时快速按下e进入编辑模式
  2. 找到以linux或linux16开头的那一行,在行尾追加rd.break(RHEL/CentOS 7 及以后)或init=/bin/bash(较老的 6.x 版本、Debian/Ubuntu 也支持)
  3. 按Ctrl + X或F10启动
  4. 如果用的是rd.break,系统会进入switch_root提示符,根文件系统被挂载在/sysroot。执行:
mount -o remount,rw /sysroot chroot /sysroot passwd root touch /.autorelabel exit reboot

这里有个关键动作:touch /.autorelabel。如果系统启用了 SELinux,直接在 chroot 环境里修改/etc/shadow会导致文件的 SELinux 上下文错乱,重启后可能登录失败。autorelabel文件会触发系统在下次启动时自动重建文件安全上下文,避免这个问题。

如果用的init=/bin/bash方式,流程更直接:

mount -o remount,rw / passwd root exec /sbin/init

2.3 云端场景:VNC/救援模式与系统盘挂载

现在的服务器大量部署在云环境,单用户模式操作起来不太方便——你没法直接"按键盘"进入 GRUB 菜单,即使能通过 VNC 进入,时机也很难把控。这时更稳妥的做法是用云厂商的"救援模式"或"重置密码"功能。不同平台叫法略有差异,原理大同小异:云平台会临时把系统盘挂载到一台救援实例上,你在救援系统里挂载原系统盘,然后修改密码文件。

这种方式的核心是直接操作/etc/shadow文件,而不是运行passwd命令。你需要知道密码的存储格式:以$分隔,$id$salt$hash,id 不同表示哈希算法不同,常见的有$1$(MD5)、$5$(SHA-256)、$6$(SHA-512)、$y$(yescrypt,新版本常见)。你可以在救援系统里执行:

chroot /mnt/root echo 'root:你的新密码' | chpasswd

或者用 openssl 生成哈希后直接写入 shadow 文件:

openssl passwd -6 '你的新密码'

然后把生成的哈希字符串替换/etc/shadow中 root 行第二个字段的内容。需要特别小心:shadow 文件字段之间有明确的冒号分隔,一个都不能错;字段位置错了会导致无法登录,甚至 PAM 认证直接失败。

我个人更推荐用chpasswd而不是手改文件,因为chpasswd会帮你处理哈希生成和写入格式,出错概率更低。但前提是你已经chroot进原系统环境,并且网络功能不受影响。

3. 修改root密码必须同步处理的三处联动

3.1 SSH 登录限制与 PermitRootLogin

改完 root 密码,大多数人会顺手测试ssh root@服务器IP,结果发现依然无法登录,第一反应是"密码没改成功"。实际上很可能是 SSH 服务配置里根本没允许 root 通过密码登录。

/etc/ssh/sshd_config里有这么几个关键参数:

  • PermitRootLogin yes:允许 root 密码登录(高危,不建议)
  • PermitRootLogin prohibit-password:允许 root 使用密钥登录,禁止密码登录(默认策略,安全性较好)
  • PermitRootLogin no:完全禁止 root 登录

如果你改 root 密码是为了让某个同事能通过 SSH 用 root 登录,结果PermitRootLogin是prohibit-password,那你密码改得再对也白搭。修改sshd_config后要重启 SSH 服务(systemctl restart sshd或service ssh restart),并且先测试新配置无误再关闭当前连接,防止重启 SSH 失败把自己锁在外面。

还有一点值得注意:修改 root 密码不会影响已建立的 SSH 连接。会话密钥在连接建立时已经协商完毕,密码只在初始认证时使用。所以你改密码时正开着几个 SSH 窗口,它们不会掉线,但新窗口必须使用新密码。这个机制经常让新手产生"密码到底有没有生效"的困惑。

3.2 sudo 与 PAM 的关联影响

root 密码和普通用户的 sudo 提权看似互不干扰,但在 PAM 配置层面它们共享同一套认证栈。很多系统在/etc/pam.d/sudo里会引用system-auth或password-auth,里面包含pam_pwquality、pam_pwhistory等模块。

如果你在修改密码时发现新密码无法通过复杂度验证,比如"密码与用户名相同""密码是回文""长度不足",都是pam_pwquality在起作用。可以临时查看它的配置文件/etc/security/pwquality.conf,里面有minlen、dcredit、ucredit、lcredit、ocredit这些参数,分别控制最小长度、数字、大写、小写、特殊字符的得分要求。

在实际生产环境里遇到过一个比较隐蔽的问题:某系统通过 LDAP 或 NSS 的sssd做账号统一认证,本地/etc/shadow里也有 root 条目,但 root 的实际认证走了 LDAP。此时passwd root修改的是本地密码,可登录时认证的是 LDAP 密码,两边对不上,就会一直报"密码错误"。遇到这种混合认证环境,先检查/etc/nsswitch.conf中passwd那行是否包含sss或ldap,再用getent passwd root看账号来源。

3.3 定时任务、脚本里的旧密码依赖

这条属于"改之前没想到,改之后才发现"的经典场景。很多服务器上有各种脚本、服务、定时任务,它们的连接凭据可能用的就是 root 密码。比如某运维同学写了一个 Python 脚本,通过 SSH 跳板机连接目标服务器执行命令,脚本里硬编码了 root 密码。root 密码一改,第二天所有自动化任务全部失败,日志显示"Authentication failed"。

这一类问题不在技术层面,而在管理层面。我的建议是:凡是改 root 密码,先全局搜索一遍有没有硬编码密码的配置文件。用关键词找一下:

grep -rn "password\|passwd" /opt /home /etc/cron* 2>/dev/null

更稳妥的做法是推动环境里使用密钥认证或者集中的密钥管理方案,让服务和脚本不再依赖 root 密码。如果暂时改不了,那就在修改密码后的变更记录里列出"需同步更新 XXX 脚本",逐项确认。

另外,数据库、消息队列等中间件的服务账号通常不是 root,一般不受影响。但如果有脚本用 root 权限去执行mysqladmin之类的管理命令,那可能间接受到影响,需要一并排查。

4. 完整实操演示:从登录到验证

4.1 实操前的准备与快照/备份

无论场景多紧急,改密码前都应该做一个最小化的备份或快照。云服务器可以开一个磁盘快照,物理机至少把/etc/shadow、/etc/passwd、/etc/sshd_config这几个关键文件复制到安全位置:

cp /etc/shadow /root/backup_shadow_$(date +%F) cp /etc/passwd /root/backup_passwd_$(date +%F) cp /etc/ssh/sshd_config /root/backup_sshd_$(date +%F)

备份的意义在于:你可能会手误改错字段,或者系统在改密码过程中意外断电,导致 root 无法登录。有备份就能在救援模式下快速恢复,不至于被锁在系统外。

另外,建议在业务低峰期操作。修改密码本身对运行中的服务没有影响,但万一改挂了需要重启,那影响面就大了。我在某电商系统做过一次紧急密码修改,改完发现 PAM 配置有问题,重启 SSH 后无法登录,只能硬重启服务器,结果几十个线上实例一度脱离了负载均衡,还好是低峰期,没有酿成大事故。

4.2 passwd 修改与密码强度检验

在能正常登录的前提下,完整的操作序列是这样的:

# 1. 先确认当前的认证配置 grep -E "PASS_MAX_DAYS|PASS_MIN_DAYS|PASS_MIN_LEN" /etc/login.defs # 2. 查看 root 当前状态 passwd -S root # 3. 修改密码 passwd root # 4. 验证修改结果 passwd -S root chage -l root

chage -l root会输出密码上次修改时间、密码过期时间、密码过期后的宽限天数等信息。如果显示"密码过期"或者"密码已失效",说明之前有策略把有效期设置得很短,你需要用chage调整:

# 设置密码永不过期(仅测试环境,生产环境请按安全策略设置) chage -M 99999 root

生产环境里强烈不建议设置永不过期。如果公司有等保要求,通常密码有效期是 90 天以内。你可以这样设置:

chage -M 90 root chage -W 7 root

这样密码 90 天后过期,过期前 7 天开始警告。

4.3 单用户模式重置完整流程记录

我找了一台模拟的 Rocky Linux 9 测试机走了一遍完整流程,记录如下:

重启后在 GRUB 启动菜单按e,找到以linux开头的那一行,在末尾加上rd.break(注意前面的空格),然后按Ctrl + X启动。系统会进入类似这样的提示符:

switch_root:/#

此时根文件系统挂载在/sysroot,但默认是只读。依次执行:

mount -o remount,rw /sysroot chroot /sysroot

chroot之后你已经切入了原先的系统环境,可以正常执行passwd root。输入两次新密码后,执行touch /.autorelabel,然后连续exit退出 chroot 和 switch_root,系统会自动重启。

重启后 SELinux 会自动执行标签重建,视文件多少可能需要几分钟到几十分钟。这期间 SSH 可能无法登录,控制台可能显示类似Generating /etc/ssh/ssh_host_key的提示。等它完成,root 的新密码就生效了。整个过程最关键的三个动作:remount,rw、passwd root、touch /.autorelabel,少一个都可能有隐患。

有些系统会强制要求先输入 root 密码才能进入单用户模式(比如/etc/sulogin配置了SINGLE=/sbin/sulogin),那你就得先知道原密码,或者用救援盘、云控制台等方式绕过去。如果单用户模式也进不去,那就只能走系统盘挂载修改/etc/shadow的路子,这也是云端环境的主要方案。

4.4 修改后验证清单

密码修改完,不是直接宣布结束。我习惯按这个清单逐项验证,避免第二天被叫起来处理"密码不对"的工单:

  1. 新开一个 SSH 会话,用新密码登录 root,确认成功
  2. 执行sudo -i检查普通用户提权是否正常(如果有多个管理员账号)
  3. 检查系统日志里有没有认证错误:journalctl -u sshd --since today | grep -i fail
  4. 确认相关的计划任务是否还能正常执行(重点看有连接外部服务器任务的)
  5. 如果环境里有监控系统或堡垒机,确认它们的账号同步是否有延迟

这一步看起来繁琐,但能避免大量"看似无关"的后续问题。我见过有人改完密码后,半夜被监控告警吵醒——原来是采集 agent 使用了旧密码连接数据库,改完 root 密码后全部失联,这种坑改之前就要预料到。

5. 常见报错与坑位排查手册

5.1 "Authentication token manipulation error" 与只读文件系统

这个报错大概是修改 root 密码时最经典的一类。它表示passwd尝试写/etc/shadow时失败了。常见原因有:

  • 文件系统挂载为只读(单用户模式下最常发生,忘记remount,rw)
  • /etc/shadow被chattr +i加了不可变属性
  • SELinux 阻止了对 shadow 文件的写入(少见但确实会遇到)
  • 磁盘空间满,导致无法写文件

排查顺序建议是先看挂载状态:

mount | grep -E "/ | /etc"

再看文件属性:

lsattr /etc/shadow

如果 output 里有i,执行chattr -i /etc/shadow后再改密码。如果是磁盘满,先清理空间再操作。

5.2 "user 'root' does not exist" 类异常

在单用户模式下 chroot 之后执行passwd root,偶尔会报用户不存在。这通常是因为 chroot 后/etc/passwd和/etc/shadow与当前环境的 NSS 配置不一致。比如/etc/nsswitch.conf里passwd那行配置了files sss ldap,但 chroot 环境里无法访问这些外部服务。

解决办法是在 chroot 前先确认:

cat /etc/nsswitch.conf | grep passwd

如果其中有ldap或sss,可以尝试直接编辑/etc/shadow,或者临时修改/etc/nsswitch.conf只保留files。改完再执行passwd root,成功后再恢复正常配置文件。

5.3 修改后仍提示密码错误:时间同步与缓存问题

有一种特别隐蔽的情况:密码确实改成功了,chage -l root显示正常,但登录就是提示密码错误。我曾经在一台 NTP 时间严重偏移的服务器上遇到过——/etc/shadow里记录的是基于系统时间戳的"上次密码修改时间",系统时间比真实时间快了整整一年,PAM 认为密码已经过期,要求修改但又不接受新密码。

处理方式是校正系统时间,并同步硬件时钟:

timedatectl set-ntp true hwclock --systohc

然后用chage -d today root把密码修改时间重置为当前日期,再试登录,问题就消失了。这类故障频率不高,但一旦遇到,如果不是对内部机制有了解,排查起来相当耗时。

5.4 排查速查表

现象可能原因快速验证处理方法
passwd 报 Authentication token manipulation errorshadow 只读/chattr +i/磁盘满lsattr, df -h解除只读、解除 i 标记、清理空间
修改成功但新密码无法登录PAM 策略过期/sshd 限制/SELinux 上下文错误chage -l, getenforce调整登录策略、更新上下文、autorelabel
远程 SSH 无法 root 登录PermitRootLogin 配置限制grep PermitRootLogin修改 sshd_config 并重启服务
单用户模式提示用户不存在混合认证源/NSS 配置cat /etc/nsswitch.conf临时切 files,改完恢复
改完密码后定时任务失败脚本硬编码旧密码grep -rn "password"更新脚本、改用密钥认证
登录提示密码已过期chage 策略或系统时间异常chage -l, date调整有效期、校正时间

这个表可以直接保存下来,遇到类似问题逐行对照,大多数情况几分钟就能定位。

6. 一个容易被忽略的小技巧:用 passwd 的锁与解锁机制

很多人在修改 root 密码时不知道passwd还自带锁定和解锁功能。passwd -l root会在/etc/shadow的密码哈希前加一个!前缀,使密码认证失效;passwd -u root则去掉!,恢复密码认证。这个机制在临时禁用 root 登录时非常有用。

有一次我在处理一台被爆破的服务器,攻击者不断尝试 root 密码,虽然密码强度够高攻不进来,但日志里全是失败的 SSH 尝试。我先用passwd -l root锁掉密码登录,然后用密钥方式继续管理,等完全加固后再解锁。这个操作比直接改密码更快的阻断手段,也适合长期不直接使用密码登录的系统。

需要注意的是,passwd -l锁定的是密码认证,并不会影响 root 通过其他方式登录(比如 SSH 密钥、sudo 提权)。如果你想彻底禁止 root 登录,还是得到sshd_config和 PAM 层面去控制。

我在实际使用里还有一个习惯:修改 root 密码后,会把密码写进加密的密码管理工具,并且在服务器的变更记录里注明修改日期和原因。这不是形式主义,而是当你需要为三年前的某次操作负责时,能快速说清楚"为什么改、改了之后影响了什么"。

最后再分享一个经验:每次改密码之前,先看一眼当前系统负载和登录用户的情况。如果服务器上正有人跑着关键任务,或者当前在线用户很多,尽量避开那个时间段。这看起来和"修改 root 密码"没直接关系,但能避免因为重启、重新验证等操作引发的连带风险。做运维,稳定压倒一切。

RELATED READING

延伸阅读

更多一线实战笔记与深度复盘,助您持续精进