ARTICLE · INTELLIGENCE

战地情报 · 详情页

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

Linux虚拟机密码修改全指南:root与普通用户实操及故障恢复

Linux虚拟机密码修改全指南:root与普通用户实操及故障恢复

做运维的,谁没在虚拟机上改过密码?我自己是从命令行老用户一路过来的,但真正把“改密码”这件事彻底弄明白,还是在接手了一批又一批带 root 和普通用户权限的虚拟机之后。光说改自己的登录密码,或者帮同事重置 root 密码,就踩过不少坑:有人改了密码之后旧会话还在、有人密码明明设置成功了却死活登不上去、还有人因为不懂普通用户和 root 在修改密码时的权限差异,把一台刚交付的环境搞到需要进单用户模式才能救回来。

这篇文章就围绕“正确修改虚拟机的登录密码”展开,覆盖 root 和普通用户两种场景,从权限模型到具体命令,再到忘记密码之后的恢复方案,最后是故障排查经验。如果你是刚接触 Linux 虚拟机的运维新人,或者经常需要帮别人重置密码、管理多台测试机,那这篇文章应该能帮你少走很多弯路。我会把为什么这么做、这么做的依据是什么、有哪些细节容易忽略,都尽量说明白。

1. 修改密码这件事,先想清楚权限模型

1.1 root 修改密码与普通用户修改密码,差别到底在哪里

很多人第一次接触 Linux 时,以为改密码就是敲一行passwd的事。其实这里面的权限逻辑非常清楚:root 是系统管理员,可以修改任何用户的密码,而且不需要知道这个用户的旧密码;普通用户只能修改自己的密码,但必须先验证旧密码。

root 改自己密码时,直接执行passwd,系统不会要求你输入当前密码。这是因为 root 的身份本身就代表了最高信任等级,系统认为能坐在 root 终端前的人,就是管理员本人或获得管理员授权的操作者。root 改某个普通用户的密码时,执行passwd 用户名,同样不需要输入该用户的旧密码。这个设计背后的考虑是:管理员重置密码通常发生在用户忘记密码、账号被锁定、员工离职交接这类场景。如果重置还要旧密码,那重置就失去意义了。

普通用户执行passwd时,系统会先要求输入“当前密码”。这是身份验证的一道门槛,防止有人在用户离开终端时趁虚而入,把别人的密码改掉。即使你物理上坐在这台机器前,只要不知道旧密码,就无法修改。这一点和手机解锁、银行改密逻辑一致,核心原则是“要证明你是你”。

我见过有些刚入行的同事,用 root 帮普通用户改密码,改完还问“要不要先问一下人家的旧密码”,这种想法就是把权限模型搞混了。管理员重置密码不是窃取身份,而是行使管理职责。真正需要警惕的是另一种错误:把密码直接写在工单里,或者用明文方式发给对方。正确做法是设置一个临时密码,强制对方首次登录后修改,具体操作后面会讲。

1.2 这些密码到底存在哪:passwd 文件和 shadow 文件的关系

改密码这件事看着简单,但如果你不知道密码存在哪里,遇到“密码改成功了却还是登不进去”这种诡异问题时,就会完全没思路。

Linux 系统里有两个关键文件:/etc/passwd和/etc/shadow。在很早期的 Unix 系统里,用户密码的哈希值直接存在/etc/passwd文件里。但这个文件是所有用户都可以读取的,密码哈希暴露给所有人,就给了离线破解的机会。后来引入了 shadow 密码机制,把真正的密码哈希挪到了/etc/shadow,而/etc/passwd里只保留一个表示“密码占位”的x字段。

/etc/shadow文件权限默认是000或640,只有 root 和 shadow 组可以读写。普通用户无法直接读取这个文件,因此无法拿到密码哈希。执行passwd命令时,实际写入的就是/etc/shadow中该用户对应的那一行。

/etc/shadow中用冒号分隔了多个字段,重点看前几个:

  • 用户名
  • 加密后的密码哈希,有时会带!或!!前缀,表示账户被锁定,密码认证被禁用
  • 最近一次修改密码的日期,单位是自 1970-01-01 起的天数
  • 两次修改密码的最小间隔天数
  • 密码最长有效期天数
  • 密码过期前的警告天数
  • 密码过期后到账户被禁用的宽限天数
  • 账户过期日期

我在排查问题时,经常直接查看/etc/shadow中某个用户的记录。比如用户登录时报“密码已过期”,我就会看第 5 个字段是否设了较短的有效期;用户报“账号被锁定”,我会看哈希字段前面是不是有!。这些经验在处理虚拟机问题时候特别管用,因为虚拟机环境常常是几台一起管理,各种状态混杂,能快速定位才是效率。

用生活化一点的类比:/etc/passwd就像是公司的通讯录,谁在哪个部门一目了然,但不会写门禁密码;/etc/shadow才是物业那里保管的门禁密钥记录,只有管理员能看。改密码的本质,就是更新物业记录里的密钥信息,而不是改通讯录本身。

2. 基础操作:日常修改密码的完整流程

2.1 root 用户修改自己的密码

先讲最常见的场景:登录一台虚拟机,发现当前用的是 root 账号,想把自己的密码改掉。操作极其简单:

passwd

执行后系统会提示输入新密码,并确认一次。成功后会输出类似passwd: all authentication tokens updated successfully的信息。

这里有几个细节值得注意。

第一,root 修改自己的密码不需要旧密码,但这不代表你可以随意在别人已经登录的 root 会话里改密码。如果你是在别人授权的会话里工作,最好先确认这台机器的归属和管理约定。

第二,修改密码后,当前已经登录的会话不会被打断。很多人以为“改完密码所有登录都会掉线”,其实不会。SSH 会话在建立时已经完成了身份验证,后续通信用的是协商出来的会话密钥,与登录密码没有直接关系。也就是说,你改完密码,正在跑的任务完全不受影响。这个特性在生产环境操作时非常重要,它可以让你放心地改密码而不必担心中断正在执行的程序。

第三,如果这台虚拟机开启了 SELinux,并且你在特殊环境下改过密码,需要留意文件上下文问题。这个坑在后面的恢复流程里会细讲,日常用passwd命令正常修改则不用担心。

2.2 root 帮普通用户修改密码

场景很常见:某员工离职、密码遗忘、测试环境需要临时分配账号。直接执行:

passwd 用户名

系统会提示输入新密码两次,然后更新该用户的密码哈希。

root 帮普通用户改密码时,不需要该用户当前密码。即使这个用户当前没有密码(比如从未设置过)、甚至账号处于锁定状态,root 都可以直接重置。这就是管理员权限的意义。

有些同仁喜欢用管道一行搞定,比如:

echo "新密码" | passwd --stdin 用户名

这种方式在部分发行版上可以工作,但我不推荐在生产环境使用。原因有两个:一是命令会出现在 shell 历史记录里,密码直接暴露;二是某些发行版的passwd并不支持--stdin参数。如果你在自动化脚本里确实需要非交互式设置密码,建议改用chpasswd命令,它可以批量处理,并且配合标准输入使用更规范。示例:

echo "用户名:新密码" | chpasswd

批量修改多个用户时,准备一个文本文件,每行格式为用户名:密码,然后执行:

chpasswd < 密码文件

这种方式适合在交付虚拟机时批量初始化账号,比自己一个个敲passwd高效得多。

还有一个关键操作容易被忽略:强制普通用户首次登录后修改密码。很多团队喜欢让管理员设置一个统一的初始密码,然后要求用户第一次使用时改掉,避免长期使用公共密码。实现方法:

chage -d 0 用户名

-d 0的含义是把“最近一次修改密码的日期”设置为 0,也就是 1970 年 1 月 1 日。系统认为这个用户的密码早就过期了,因此用户下次登录时会被强制要求设置新密码。设置完成后,再执行chage -l 用户名查看密码状态,确认“上次修改密码时间”显示为“密码必须更改”。

这样做的好处是:管理员不知道用户最终设置的密码,用户自己掌握密码,安全性更高。我在给客户交付环境时,经常用这种模式:所有账号初始密码统一,交给客户后强制改密,避免交付文档里存放太多敏感信息。

2.3 普通用户修改自己的密码

以普通用户身份登录虚拟机后,执行:

passwd

系统会提示:

(current) UNIX password:

输入当前密码后,再输入新密码并确认。

这里最容易踩的坑是:新密码不满足系统复杂度要求。很多发行版默认启用了pam_pwquality模块,新密码如果太短、太简单、纯数字、与用户名相似,都会被拒绝。具体提示大概是The password fails the dictionary check - it is too simplistic/systematic之类。

普通用户修改自己的密码时,系统会强制进行强度检查。这是好事,因为很多安全事件就是弱密码导致的。如果确实需要设置一个简单的密码(比如纯测试环境),可以用 root 执行passwd 用户名来设置,root 设置的密码可以绕开复杂度检查。但请注意:这种绕过是刻意的,别用在生产环境。

另外,普通用户如果忘记了当前密码,是无法自己重置的。唯一途径是找管理员帮忙。不过这里有一个技巧:如果该普通用户拥有sudo权限,他其实可以通过sudo passwd 用户名来重置自己的密码,因为sudo授权下他以 root 身份运行命令,自然不需要自己的旧密码。这算是一个很多人不知道的“后门”。当然,前提是sudo规则允许执行passwd命令。

我在给虚拟机做日常维护时,经常需要提醒同事:不要把 sudo 权限当作万能钥匙,尤其不要把sudo授权到ALL加上不需要密码的配置。否则一旦账号被攻破,攻击者可以轻松修改系统上任意用户的密码,包括 root。

2.4 第一次设置密码与无密码登录场景

有些虚拟机创建完成后,默认只有 root 用户,或者通过 cloud-init 注入了 SSH 公钥,普通用户可能根本没有密码。此时用户可以通过 SSH 密钥登录,但从没设置过密码,也没法用密码登录。

第一次设置密码时,执行passwd,系统不会询问旧密码,直接让你输入新密码。这个流程和密码过期后的强制修改类似:系统认为当前没有有效密码,因此免去旧密码验证。

这里要特别提醒:如果你给一个用户设置了密码,但这台机器上还有 SSH 密钥登录的配置,那这个用户可以同时通过密码和密钥两种方式登录。若你想关闭其中某一种,需要调整 SSH 服务端配置。处理虚拟机的密码时,别忽略 SSH 层的控制,尤其是在开启公网访问的机器上,密码登录和密钥登录的管理策略必须清晰。

3. 忘记密码又进不去系统,如何恢复

3.1 重置思路:绕过登录验证,进入管理员环境

说实话,虚拟机上最刺激的操作之一就是 root 密码忘了。尤其是生产环境,重启和等待都会让人焦虑。但虚拟机的优势在于,你可以通过宿主机控制台直接操作,不受远程连接限制,也不需要找机房人员帮忙。

重置密码的核心思路很简单:绕过系统的正常登录验证,进入一个可以修改/etc/shadow文件的环境。常见路径有单用户模式、紧急模式、通过内核参数直接进入 shell。对于运行 systemd 的发行版(RHEL 7/8/9、CentOS 7+、Rocky Linux 等),最常用的方式是修改 GRUB 启动参数,加入rd.break。

这个方法比传统的init=/bin/bash更适合现代系统,因为它会在切换到真正根文件系统之前中断启动流程,直接给你一个 ramdisk 环境。在这个环境里,你可以把根文件系统挂载为可读写,然后 chroot 进去修改密码。

3.2 完整操作路径(RHEL/CentOS/Rocky 系)

下面步骤以 RHEL 系虚拟机为例,整个过程大约需要 5 到 10 分钟。

第一步,重启虚拟机。可以通过宿主机控制台发送重启指令,也可以强制断电后再开机。如果是远程虚拟机,只要宿主机还在,控制台一般都能用。

第二步,在 GRUB 引导菜单出现时,按e键进入编辑模式。注意动作要快,有些虚拟机默认 GRUB 等待时间非常短,可能只有 1 到 5 秒。你可以在开机时不停按方向键或Esc键,把菜单留住。

第三步,找到以linux开头的那一行,这一行里包含内核镜像、根文件系统所在分区,以及一些启动参数。定位到行尾,在末尾追加参数:

rd.break

如果启动参数里已经有quiet,可以顺手删掉,这样启动时可以输出更多日志。但这不是必需操作。

第四步,按Ctrl+X或F10启动。系统会进入一个早期用户空间环境的 shell,提示符类似于:

switch_root:/#

此时根文件系统还没有挂载,或者处于只读状态。执行以下命令,把真正的根文件系统挂载为可读写:

mount -o remount,rw /sysroot

这个命令非常关键。不执行的话,后续 chroot 后所有修改都只能写内存,重启后全部丢失。

第五步,切换到真正的根环境:

chroot /sysroot

之后你就进入了虚拟机的真实文件系统,可以像平常一样使用passwd命令:

passwd root

系统会提示输入两次新密码。执行成功后,密码哈希已更新到/etc/shadow。

第六步,这一步容易忽略但至关重要:让系统在下次启动时重新标记 SELinux 上下文。

touch /.autorelabel

在rd.break环境下,SELinux 策略并未正常加载,你创建的/etc/shadow新内容可能没有正确的 SELinux 标签。如果不触发 autorelabel,重启后很可能出现“明明密码对了,但 SSH 登录还是失败”的问题,而且查看日志会发现大量 SELinux 拦截记录。touch /.autorelabel会在系统下次启动时自动对全部文件重新打标签,整个过程可能耗时几分钟,耐心等待即可。

第七步,退出 chroot,重启:

exit reboot

重启后就可以用新密码登录 root 了。

3.3 为什么选 rd.break,而不是 init=/bin/bash

不少老教程教的是在 GRUB 启动参数中加入init=/bin/bash。在 systemd 时代,这套方法依然可用,但有一个问题:以init=/bin/bash启动时,系统直接跳过很多初始化步骤,根文件系统通常是只读挂载的。你需要手动执行:

mount -o remount,rw /

然后才能修改密码。操作上并没有难到哪去,但在某些新内核和 systemd 组合下,init=/bin/bash的流程比较“粗糙”,可能出现网络服务或其他资源没有准备就绪的奇怪问题。rd.break则是 systemd 内置的早期调试接口,流程更标准化,在 RHEL 7 之后的发行版上更可靠。

还有一个区别:rd.break停在 initramfs 的早期阶段,此时真正的根目录还没有挂载到/,所以需要chroot /sysroot。而init=/bin/bash直接进入真正的根环境,不需要 chroot。两者都需要手动重新挂载读写,这点别忘。

3.4 不同发行版的适配:Ubuntu/Debian 系

如果你管理的是 Ubuntu 或 Debian 虚拟机,恢复方法稍有不同。GRUB 界面中选择Advanced options for Ubuntu,然后选择recovery mode。进入恢复菜单后,选择root - Drop to root shell prompt。此时会进入 root shell,但文件系统是只读的,先执行:

mount -o remount,rw /

然后直接修改密码:

passwd 用户名

Ubuntu 的 recovery mode 不需要 chroot,也不需要rd.break那种复杂流程,相对简单。但要注意,Ubuntu 默认禁止 root 直接登录 SSH,如果你原本想给 root 设置密码以启用 SSH 登录,需要在/etc/ssh/sshd_config中确认PermitRootLogin配置。恢复模式下也一样,改密码只解决密码问题,SSH 登录限制是另一层。

还有一点,Ubuntu 的 root 默认没有有效密码,用户平时用sudo。如果你在恢复模式下执行passwd root,实际上是给 root 设置了一个密码,之后可以从控制台用 root 登录。但 SSH 端PermitRootLogin默认通常是prohibit-password,即禁止密码登录 root,只允许密钥。这个细节不搞清楚,就会出现“密码明明对但 SSH 登不上”的困惑。

3.5 重置密码后的安全检查

通过恢复流程重置密码后,别急着把虚拟机交付出去,先做几件事。

第一,检查/etc/shadow的权限是否正确。正常情况下应该是root属主,权限为000或640。如果变成了普通用户可读,说明恢复过程中可能有操作失误。

ls -l /etc/shadow

第二,确认密码策略不会导致新密码立即失效。执行:

chage -l root

如果看到“密码过期时间”在很近的未来,或者“密码必须更改”显示为 yes,说明该账号策略设置了强制改密。如果这是你刚设置的密码,且不想让它在首次登录时被要求修改,需要调整策略:

chage -M 99999 用户名

第三,查看认证日志,确认系统启动正常,没有因为重置密码产生新的异常。常见的有:

journalctl -b | grep -i selinux

如果在日志里看到大量 SELinux avc denied,说明 autorelabel 可能没触发成功。手动检查一下/下是否存在.autorelabel文件,如果文件还在,说明系统还没完成重新标记,需要再重启一次。

4. 修改密码之后,必须检查的几件事

4.1 旧会话、定时任务、服务的连带影响

修改密码这件事,表面上是更新一个哈希值,但它可能会影响系统里其他依赖密码认证的环节。先把最常见的三个连带影响说明白。

第一个是旧会话问题。修改密码不会注销已经登录的 SSH 会话,也不会中断正在运行的终端命令。原因前面说过,已建立的会话不依赖密码做后续通信。但要注意一种特殊情况:如果有人在 vim 或 sudo 等待输入密码的过程中,你突然改了他的密码,那他正在输入的那个密码就会失效,他需要重新执行命令并输入新密码。这种场景在多人共用一台测试虚拟机时经常发生,命令行上的提示“sorry, try again”往往就是这么来的。

第二个是定时任务。很多运维脚本会在 crontab 中使用带密码的远程连接命令,比如通过 SSH 或 scp 连接其他机器。如果你修改了本机用户的密码,但远端机器上保存的仍是旧密码(比如 SSH 客户端配置里存放了密码),那么定时任务可能在下一次执行时认证失败。注意,现代系统里 SSH 通常用密钥认证,不受影响,但一些脚本仍然用密码认证,改密码前最好翻一遍 crontab 和对端机器上的认证配置。

第三个是 PAM 认证的服务。比如图形登录界面、sudo、su,它们都通过 PAM 模块验证密码。只要密码修改成功,这些服务就会自动使用新密码,没有额外配置负担。但如果你修改的是服务账号(比如某些应用专用账号),而这个服务自己的配置文件里写死了旧密码,那就需要同步更新,否则服务认证失败。典型例子是数据库备份脚本、监控客户端,它们可能用系统账号做认证,改密码时要记得同步。

4.2 密码策略与过期时间:chage 命令解析

Linux 的密码不只包含密码本身,还有一组生命周期策略,储存在/etc/shadow的多个字段中。日常管理中,查看密码状态的命令是chage:

chage -l 用户名

输出内容包括:

  • 最近一次修改密码的日期
  • 密码过期时间
  • 密码失效时间
  • 账户过期时间
  • 两次修改密码的最小间隔天数
  • 两次修改密码的最大间隔天数
  • 密码过期前的警告天数

对虚拟机运维来说,最常遇到的是“密码过期导致无法登录”的问题。执行chage -M -1 用户名可以把密码设置为永不过期。-M表示最大有效天数,-1代表不限制。同理,chage -m 0 用户名表示用户可以随时修改密码,不受最小间隔限制。

全局默认策略在/etc/login.defs文件中配置,包括:

PASS_MAX_DAYS 99999 PASS_MIN_DAYS 0 PASS_WARN_AGE 7

如果你用脚本批量创建用户,并希望统一设置密码策略,修改/etc/login.defs后再创建用户就会自动生效。对已经存在的用户,则需要逐个用chage调整。

我在交付虚拟机时,通常会把测试环境的密码策略放宽,设置PASS_MAX_DAYS 99999,避免出现“放假回来发现密码过期,导致监控和备份全部失败”的尴尬。生产环境则按合规要求设置较短有效期,同时提醒业务方提前改密,避免密码过期引发大面积故障。

4.3 SSH 登录与密码修改的联动关系

修改密码后,原来能用的 SSH 登录方式不一定继续有效,这取决于 SSH 服务的认证配置。重点看/etc/ssh/sshd_config里的几个参数:

  • PermitRootLogin:控制 root 是否允许 SSH 登录。默认在 Ubuntu 上是prohibit-password,即 root 不能通过密码登录,只能通过密钥登录。如果你刚给 root 改了密码,却发现 SSH 依然登不进去,先检查这个参数。
  • PasswordAuthentication:是否允许密码认证。如果为no,那你修改密码对 SSH 登录毫无帮助,所有账号都只能通过密钥登录。
  • PubkeyAuthentication:是否允许密钥认证。如果为yes,用户可以使用 SSH 密钥登录,密码就退居二线。

另外,sshd的认证流程依赖 PAM。如果 PAM 配置异常,可能出现“密码输入正确,但 SSH 立刻关闭连接”的情况。排查方式:

journalctl -u sshd -n 50

日志里会直接显示认证失败的具体原因,比如Permission denied (publickey,password)或pam_authenticate failed。

修改密码后,如果 SSH 登录一切正常,说明配置没有问题。如果登录异常,多半是密钥或 SSH 配置层面的问题,和密码本身关系不大。我在处理虚拟机交付时,会把修改密码和 SSH 验证放在同一步:改完密码后,立刻在宿主机上执行一次 SSH 登录测试,而不是等到客户反馈才发现问题。

5. 常见问题与排查技巧实录

5.1 密码正确却无法登录,先查这几处

这是运维中最高频的问题之一。用户信誓旦旦说密码没有输错,但就是登不进去。排查步骤按顺序走:

第一步,确认 Caps Lock 没开、键盘布局没有切换错误。听起来很基础,但虚拟机控制台里由于键盘布局差异,密码里的特殊字符很容易输错。尤其用宿主机控制台操作时,宿主机的键盘布局可能和虚拟机不同,导致@、#、$这些符号错位。

第二步,查看/etc/shadow中该用户的密码字段。如果哈希前有!或!!,说明账户被锁定了。解锁命令:

passwd -u 用户名

如果是 root 锁定,需要进入恢复模式修改,这和忘记 root 密码流程一样。

第三步,检查 PAM 日志和认证日志:

journalctl | grep -i "authentication failure"

日志里会明确显示失败原因,比如user not known、locked、password expired。看到具体原因后,对症处理比盲目重置密码高效得多。

第四步,检查/etc/shadow文件权限。用ls -l /etc/shadow查看,如果权限异常(比如其他用户可读),先修正权限:

chmod 000 /etc/shadow

这个文件一旦权限放宽,匿名用户就有机会离线破解密码,安全风险极大。

5.2 修改了他人密码,结果对方报“会话异常”

场景重现:管理员帮某用户重置了密码,用户当天还能正常登录。第二天却打电话说“连不上了”。原因通常是两种。

第一种是用户在登录界面输入了旧密码,但系统已经改成新密码,用户不知道密码被重置过。这种情况多见于密码重置后没有及时通知。我在工程交付时,习惯在重置密码后,用邮件或消息通知用户,并附上首次登录后强制改密的提示,这样能避免大量“密码不对”的反馈。

第二种是用户当前的 SSH 长连接或后台服务仍在用旧密码做认证。修改密码后,已建立的会话不会断开,但用户可能没意识到,某天重新登录时才发现密码变了。此时需要做的不是解释,而是确认用户是否知晓新密码,以及是否已执行改密。

避免这类问题的最佳实践是:重置密码时直接设置一个临时密码,并用chage -d 0强制用户在首次登录时修改。这样用户会立刻知道密码被重置过,并主动设置属于自己的新密码。管理员不需要保留用户的实际密码,安全隐患也小很多。

5.3 提示 password has already been used

有些发行版会启用密码历史记录功能,防止用户反复使用同一批密码。如果你设置的新密码和之前的某个旧密码相同,系统会拒绝,并提示“密码已经被使用过”。

相关配置在/etc/pam.d/system-auth或/etc/pam.d/password-auth中,pam_unix.so模块的remember参数控制记住多少个旧密码。例如:

password sufficient pam_unix.so remember=5

表示最近 5 次用过的密码都不能再次使用。

省事的方法是设一个完全不同的、随机生成的新密码,不依赖记忆。如果实在想回到某个特定密码(比如统一口令),可以用 root 直接执行:

passwd 用户名

这个操作不走普通用户的密码历史检查,可以设置任意密码。但要注意,即使 root 设置了与历史相同的密码,用户在下次登录后依然受密码策略约束,如果策略要求定期更换,后续再次修改时仍会触发历史检查。

5.4 密码长度与复杂度限制,为何总被拒绝

新用户在设置密码时经常遇到“密码太短”“密码不符合要求”之类的报错。这是pam_pwquality模块在起作用,它根据配置检查新密码的强度。相关配置在/etc/security/pwquality.conf中,常见参数有:

  • minlen:密码最小长度
  • dcredit:必须包含的数字个数要求
  • ucredit:必须包含的大写字母个数要求
  • lcredit:必须包含的小写字母个数要求
  • ocredit:必须包含的特殊字符个数要求

比如:

minlen = 12 dcredit = -1 ucredit = -1 lcredit = -1 ocredit = -1

-1表示至少包含 1 个对应类型的字符。默认配置下,密码包含数字、大小写字母和特殊字符才符合要求。

如果测试环境不关心密码强度,可以临时降低要求,或者干脆关闭复杂度检查。但生产环境我建议保留。虚拟机一旦被爆破,影响面比物理机更大,因为攻击者可以快速复制快照、迁移、横向移动。

有一种折中做法:密码长度设长一点,复杂度要求低一点。长密码比复杂密码更容易记忆,也不容易被字典破解。比如mountain-river-sunset-2024这样的密码,长度足够,不强制特殊字符,安全性也不差。我在管理多台虚拟机时,经常用随机生成的密码配合 KeePass 之类的工具管理,而不是靠大脑记。

5.5 改完密码后,某些服务或应用突然不可用

这种问题最让人头疼,因为表面上改密码是“纯系统操作”,怎么会影响应用?实际上,可能影响的途径有几种。

第一种是应用配置里写死了用户密码。比如数据库备份脚本用/root/.my.cnf存储密码,或者某个服务用系统账号做 PAM 认证。改密码后,这些配置文件里的旧密码失效,服务自然报错。排查方式:查看相关服务的日志,通常在认证失败处能看到Access denied或Authentication failed。

第二种是定时任务里的加密连接。检查 crontab:

crontab -l -u 用户名

如果任务里包含 scp、rsync、ssh 等命令,并且使用了密码认证,改密码后就要同步更新对端机器的认证信息。更稳妥的方式是改用密钥认证,彻底摆脱密码变更带来的影响。

第三种是 D-Bus 或 systemd 服务使用了pam模块,但配置了固定密码。比如某些图形化虚拟化管理工具,会通过 systemd 的 user service 调用 PAM 验证,密码一变,服务的下一次认证就会失败。这种问题通常重启相关服务或重新登录即可解决,但如果是常驻服务,需要确认服务配置是否引用系统账号密码。

我把这类问题归结为“改密码也要有变更管理意识”。在生产环境,改密码前先梳理哪些服务依赖该系统账号认证,属于比较标准的运维素养。

6. 一些关于密码管理的习惯与建议

做虚拟机运维越久,越觉得“修改密码”这件事,技术本身只是很小一部分,更重要的是操作习惯和变更意识。分享几个我自己养成的习惯,供参考。

第一,给每台虚拟机设置独立的登录密码,不要所有机器共用同一套。一旦某个环境的密码泄露,所有环境都会暴露。对测试机可以宽松一些,但生产机和开发机必须隔离。

第二,记录密码时不要写在纯文本的工单或运维文档里。可以用密码管理器统一管理。对服务器这种高频访问的资源,密码管理器加二次验证是比较稳妥的组合。

第三,对公网可达的虚拟机,尽量使用 SSH 密钥登录,关闭或限制 root 密码登录。密钥比密码难破解,而且密钥不会因为密码策略过期而失效。

第四,改完密码后马上在控制台测试一遍,确认能登录再离开。这能避免“改完密码自己都没验证,交付给业务方才发现密码根本不对”的情况。尤其通过rd.break重置密码后,必须完整走一次重启、登录、验证的流程。

第五,涉及 root 密码的变更,尽量选择业务低峰期操作。即使操作本身不影响现有会话,但如果后续需要重启虚拟机,影响范围就不可控了。

我在实际工作中踩过最重的一次坑,是给一台承载线上服务的虚拟机重置 root 密码。当时用rd.break重置后,跳过了touch /.autorelabel,结果重启后 SSH 登录被 SELinux 拦截,控制台登录后服务也无法正常拉起。最后花了将近半小时重新登录并手动触发 relabel 才恢复。从那以后,我每次重置密码都会强制自己走一遍完整的检查清单,包括确认 autorelabel 文件存在、重启后验证 SELinux 状态、用chage -l检查密码策略。这些检查看着繁琐,但每一条都在真实环境中救过急。

虚拟机密码管理不像想象中那么难,但也不像一条passwd命令那么简单。理解权限模型、掌握恢复流程、知道改完密码后要检查哪些关联点,基本上就能覆盖绝大多数场景。下次再遇到“密码忘了”“改完登不上”“重置后服务异常”,先回到这篇文章里的排查思路,大概率能在几分钟内找到方向。

RELATED READING

延伸阅读

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