☰
Linux root密码忘记?用GRUB引导重置的实战指南
2026/10/9 3:16:01 网站建设 项目流程

机房跑着一堆 Linux,突然有一天 root 密码不记得了,或者交接文档里就没写这个密码。大部分人的第一反应是重装系统,但只要你还能摸到物理机或者 IPMI 控制台,这个局面根本不需要动系统。所谓"破解"root 密码,在 Linux 的世界里更准确的说法应该是"重置",因为系统本身留下了正规的恢复通道,只是需要你绕开正常的登录流程,直接进到一个能改密码的环境里。

这篇文章写给谁?运维、开发、实验室管理,甚至只是在家玩 CentOS 和 Ubuntu 的折腾党。内容涵盖 RHEL/CentOS 系的 rd.break 大法、Debian/Ubuntu 系的 init=/bin/bash 救援法,顺带把 MySQL/MariaDB 的 root 密码重置也一起讲了,因为排障的时候系统和数据库经常是一起出问题的。整个过程我会把每一步的原理、为什么这样操作、以及容易翻车的细节都拆开说,保证你照着做能落地。

1. 重置 root 密码之前,先把这三件事想清楚

1.1 "破解"和"重置",其实差在了入口上

很多人一听到"破解 root 密码"就想到暴力穷举、彩虹表、内核漏洞这些词,实际上运维场景里 99% 的 root 密码重置,跟"破解密码哈希"没有半毛钱关系。 Linux 把 root 密码的哈希存放在 /etc/shadow 里,正常情况下你登录系统后输入密码,系统会计算这个输入的哈希值,和 shadow 文件里的值比对。但要重置密码,根本不需要去解这个哈希,因为系统启动过程中,只要你能在引导阶段插入干预,就能拿到一个不经过登录认证的 shell。

所以你在做这件事之前,需要明确一个事实:你没有在"破解"密码本身,而是在利用 BIOS/GRUB 引导流程里的可干预性。只要机器允许你编辑内核启动参数,密码就是一层纸。真正的"破解",那是没有物理访问权、没有引导权的前提下才需要做的事情。

1.2 动手前必须确认的前置条件

别一上来就重启服务器,先确认下面几件事都满足,不然你可能把自己锁在机器外面:

  • 有可用的控制台入口:物理键盘接显示器、IPMI/BMC 的远程 KVM、或者云厂商的 VNC 控制台都必须能进,并且能看到 GRUB 菜单。纯 SSH 登录是做不到的,因为系统引导已经完成了,你干预不了内核参数。
  • 确认磁盘没有做全盘加密,或者你知道 LUKS 的密钥:如果你的根分区用了 LUKS 加密,重置密码仍然可以操作,但前提是你得在引导过程中输入 LUKS 密码来解锁。如果你连 LUKS 密码都不知道,那后面所有步骤都卡在解锁这一步,这种情况只能找持有密钥的人。
  • 确认 GRUB 没有设置密码保护:有些安全策略比较高的环境,会在 GRUB 里配 username/password,编辑启动菜单时必须先输入 GRUB 密码。这种环境你要是没有 GRUB 密码,重置流程同样走不通。
  • 确认 SecureBoot 不会拦你:大多数主流发行版对 SecureBoot 的处理是:你改了内核命令行参数,SecureBoot 仍然会放行,因为签名校验的是内核镜像本身,不是启动参数的完整性。但如果服务器开启了类似 TPM 度量启动、或者固件层面禁用了未签名引导项,你可能进不了修改后的菜单项。

这些前置条件里,我自己踩过的坑是:以为远程 KVM 能看见 GRUB,结果那台老服务器的 BMC 固件输出画面延迟了三分钟,启动菜单早就过去了。所以实际操作前,建议先在 BMC 里进入 BIOS 界面加长 GRUB 菜单等待时间,或者临时把 GRUB_TIMEOUT 改大。

1.3 root 密码到底存在哪

老规矩,先把概念理清。Linux 的用户密码信息分两个文件:

  • /etc/passwd:存放用户名、UID、GID、家目录、shell 等基本信息,密码字段一般显示为 x。
  • /etc/shadow:真正存密码哈希的地方,只有 root 和 shadow 组可读。

shadow 文件里 root 那行长这样:

root:$6$7kL0N2sH$d9mQ...:19000:0:99999:7:::

第二段是密码哈希,$6$ 表示 SHA-512 加密,$y$ 是 yescrypt 算法(新版本 Debian/Ubuntu 常见),$1$ 是 MD5。如果这个字段显示为!或者*,则表示该账户被锁定,无法用密码登录。

知道这个结构有什么用?后面改密码时,你其实有两种选择:一种是老老实实运行 passwd 命令,系统会帮你生成合法的哈希并写入 shadow;另一种是手动改 /etc/shadow 里的字段。我强烈建议选 passwd,原因后面讲 Debian 系的时候会具体说明。

2. RHEL/CentOS 系主流重置法:rd.break 带来的 dracut 紧急 shell

RHEL/CentOS 7、8、9,包括 Rocky Linux、AlmaLinux 这些下游发行版,最经典的重置 root 密码方法是往内核启动参数里加一个rd.break。它的作用是在 dracut 构建的 initramfs 接管系统、但还没切换到真正根文件系统的时候,弹出 break 点,给你一个switch_root:/#的紧急 shell。这一步发生在系统进入正常的 multi-user 环境之前,你不需要输入任何密码就能进去。

2.1 编辑 GRUB 启动项的完整操作

过程是这样的:

  1. 重启机器,在 GRUB 菜单出现时快速按 e 进入编辑模式。菜单停留时间默认只有几秒,错过的话就再重启一次。
  2. 找到以linux16(旧版 CentOS 7)或linuxefi(UEFI 引导)开头的那一行,这一行参数很长,包含 vmlinuz 路径、root 分区定位、各种内核参数。
  3. 把光标移到这一行的末尾,加一个参数:rd.break。注意前面要有空格。
  4. 按 Ctrl+X 或 F10 启动这个修改过的菜单项。

启动过程中你会看到系统走到 initramfs 阶段后停下来,出现类似这样的提示符:

switch_root:/#

到了这一步,你已经拥有了一个临时的、但权限足够大的 shell。这个 shell 运行在内存里的 initramfs 环境中,还没有真正切到硬盘上的根文件系统。

2.2 重挂 /sysroot 并 chroot 改密码

在 dracut 的紧急 shell 里,硬盘上的真实根文件系统被挂载在/sysroot目录下,但默认是只读挂载。直接改密码你会得到 read-only file system 的错误。所以第一步先重挂为可写:

mount -o remount,rw /sysroot

然后用 chroot 把自己切入到真实的根文件系统:

chroot /sysroot

这时候你的目录已经变成硬盘上的/了,可以像平时登录系统后一样操作。执行:

passwd root

系统会提示你输入两次新密码。输入时屏幕不显示字符,这不是键盘坏了,自己注意输入一致。

改完后别急着退出,还有一个关键的善后步骤。如果你刚才进入时没有在内核参数里加enforcing=0,那么系统仍然处于 SELinux enforcing 状态。你在 chroot 环境下修改了 /etc/shadow,这个文件的 SELinux 上下文可能不对,重启后系统会因为文件标签错误而拒绝正常启动,或者出现各种服务起不来的诡异问题。

所以要在 chroot 环境里创建一个标记文件:

touch /.autorelabel

这个文件的含义是:下次系统启动时,强制对所有文件系统执行一次 SELinux 重新打标签。这一步耗时可能较长,视分区大小从几分钟到十几分钟不等,但能保证你的修改被正确纳入安全上下文。

然后连续退出:

exit exit

或者直接:

reboot -f

系统会自动重启,正常情况下你就能用新密码登录 root 了。

2.3 为什么有人推荐同时加 enforcing=0

我在不少恢复教程里看到过一种操作:在编辑内核参数时不仅加rd.break,还会加一个enforcing=0。这两者的组合效果是:系统以 SELinux 宽松模式进入,你改完密码后不需要 touch /.autorelabel,也不用等待全盘重打标签的漫长过程。

两种方式怎么选?我的建议是:

  • 如果你的机器上跑着重要业务、不能忍受重启后额外花十几分钟做 autorelabel,那就加enforcing=0,改完密码直接重启进入,后续再自己手动恢复 SELinux enforcing 模式。
  • 如果你的情况是"重置完密码机器要重新部署",那我推荐老老实实走 autorelabel,这是最不容易留隐患的路径。

另外要提一个容易漏掉的细节:不管你有没有加 enforcing=0,改动内核参数都只是临时生效,只对这一次启动有效。重启后 GRUB 会恢复正常参数,不需要你改回来。

3. Debian/Ubuntu 系:init=/bin/bash 单用户救援的利与弊

Debian 和 Ubuntu 是另一大分支,虽然它们也是 GRUB 启动,但走的思路和 rd.break 不太一样。你可以用init=/bin/bash让内核在挂载根文件系统后直接启动一个 bash,而不是启动 systemd/PID1,这样既绕过了登录过程,也跳过了所有守护进程。这个方法对 Debian、Ubuntu、以及很多基于它们的国产发行版都有效。

3.1 从 GRUB 的 linux 行下手

操作同样从 GRUB 菜单按 e 开始。找到以linux开头的那一行,典型的 Ubuntu 长这样:

linux /boot/vmlinuz-5.15.0-86-generic root=UUID=xxxxxx ro quiet splash

你需要做两个修改:

  1. 把参数里的ro改成rw,让内核在挂载根目录时直接以读写方式挂载,省得进 shell 后再手动重挂。也可以不改,进 shell 后执行 mount -o remount,rw /,但多一步不如少一步。
  2. 在行尾添加init=/bin/bash。

按 Ctrl+X 启动后,系统会直接掉进一个 root shell,提示符类似:

bash: no job control in this shell root@(none):/#

看到 no job control 提示很正常,因为你没有完整的系统初始化环境,后台任务管理什么的都用不了,但执行改密码命令绰绰有余。

3.2 进 shell 后的密码处理逻辑

到了这个 bash 里,第一件事是确认根文件系统确实是可写的,执行 mount 或者直接尝试 passwd。如果你的 awk 过程忘了把 rw 加上,现在补一下:

mount -o remount,rw /

然后运行:

passwd root

输入两遍新密码即可。

这里我要特别强调一下:别因为图省事去手动编辑 /etc/shadow。网上有些教程会让你把 root 那行的密码哈希字段删掉、改成空,然后恢复后用无密码登录,再自己设置密码。这个做法风险极高,新版系统的 PAM 配置可能直接禁止空密码登录,更别提你把哈希搞错格式导致系统识别不了账户。用 passwd 命令生成哈希,系统会按当前默认算法计算,并处理好各字段的轮换规则。这是最稳妥的方案。

3.3 用 single 或 systemd.unit=rescue.target 的坑

有人会问:既然 Ubuntu 有单用户模式 / recovery mode,直接进那个不好吗?要小心,systemd 体系的单用户模式(rescue.target)会要求你输入 root 密码,因为 systemd 启动到 rescue 之前会请求管理员认证。你要是在忘记了 root 密码的场景下用 rescue,结果就是卡在密码提示,只能再重启一次。

这也是为什么在找回 root 密码的场景里,init=/bin/bash比 rescue.target 更直接——它不是通过 systemd 的认证流程,而是直接替换了 PID1,整个登录机制就被跳过了。

不过在选定 init=/bin/bash 时也有一点要注意:因为 PID1 被替换,你等于绕过了文件系统挂载、网络服务初始化、设备节点配置这些流程。改完密码后,别指望这个系统状态能直接继续跑业务,必须重启回正常模式。

4. 不只是系统:给 MySQL 和 MariaDB 的 root 做"规范复位"

系统 root 密码解决了,但很多真实场景里,你接手的机器除了 Linux 系统密码不知道,数据库的 root 密码也一并丢了。MySQL 和 MariaDB 的密码重置原理和系统层面不一样,但也有一套正规方法。这套方法在热词里出现频率极高,因为数据库出问题往往和服务器密码问题是前后脚的事。

4.1 停库并进入 skip-grant-tables 模式

MySQL/MariaDB 在启动时,如果加了--skip-grant-tables参数,启动后会直接忽略权限表,任何用户都能以 root 身份无密码连进数据库。这当然很危险,所以连接时要顺手加上--skip-networking,让它只允许本地 socket 连接,避免远程机器趁这个窗口连进来。

具体操作是这样的,先停止数据库服务:

systemctl stop mariadb

如果你是 MySQL 8.0,命令是 systemctl stop mysqld。然后以前台方式临时启动一个跳过权限表的进程:

mysqld_safe --skip-grant-tables --skip-networking &

这个进程会一直挂着,你操作完后要 kill 掉它再正常启动服务。有的发行版把 mysqld_safe 也改成了 mysqld,注意看自己的进程名。你也可以选择修改配置文件,在 [mysqld] 段下临时加上 skip-grant-tables 再 systemctl start,改完再删掉重启,两条路等效。

4.2 在空授权模式下修改密码

启动成功后,不用密码直接连进去:

mysql -u root

注意这里不需要 -p,因为权限表已经被跳过了。进入 MySQL 命令行后,先执行一条关键命令:

FLUSH PRIVILEGES;

这一步很重要。因为 skip-grant-tables 模式下权限表内容没有被加载,FLUSH PRIVILEGES 可以强制让 MySQL 重新加载权限表,并让后续的 ALTER USER 语句生效。如果你上来直接 ALTER USER,大概率报错或改了无效。

然后是改密码。MySQL 8.0 和 MariaDB 的语法略有区别,我把两个都列出来:

数据库版本重置 root 密码的语句
MySQL 8.0ALTER USER 'root'@'localhost' IDENTIFIED BY '新密码';
MariaDB 10.4+ALTER USER 'root'@'localhost' IDENTIFIED BY '新密码';
MariaDB 10.2 及更老SET PASSWORD FOR 'root'@'localhost' = PASSWORD('新密码');

如果你想兼容旧版客户端/旧版驱动,MySQL 8.0 还可以显式指定认证插件:

ALTER USER 'root'@'localhost' IDENTIFIED WITH mysql_native_password BY '新密码';

改完后退出 mysql,把刚才临时用的 skip-grant-tables 进程停掉,然后正常启动服务:

systemctl kill mysqld_safe 2>/dev/null systemctl start mariadb

到这一步数据库 root 密码就复位了。

4.3 为什么不能只用 UPDATE mysql.user

网上也会有人建议你直接 UPDATE mysql.user SET authentication_string=PASSWORD(...) WHERE User='root',然后重启。这套路在 MySQL 5.7 时代偶尔能用,MySQL 8.0 之后已经完全不靠谱了,原因有两个:

一是 MySQL 8.0 的密码字段改成了 authentication_string,但真正决定认证行为的是 plugin 字段。默认的 caching_sha2_password 会做盐值处理和二次哈希,你手写一个字符串进去,它不认为那是一个合法的密码哈希,重启后你可能得到"账号无法正常认证"的结局。

二是 MariaDB 较新版本对 mysql.user 表的密码字段同样有自己的存储格式,直接 UPDATE 很容易内容损坏。

所以我的建议永远是通过 ALTER USER 来改,这走的是官方认证机制,插件行为、密码策略都会正确处理。有些环境打开了 validate_password 插件,要求密码必须达到一定复杂度,如果你的新密码太简单,ALTER USER 会直接拒绝,爆出一个 ERROR 1819,这时候换一个复杂度够的密码就行。

5. 重置完成后的善后与安全自查

密码改完了、系统能登录了,千万别觉得这事儿就完了。以我的经验,每次干完这种"打破沙锅"的操作后,都要花几分钟把善后工作做干净,不然过阵子又是同一个坑。

5.1 验证、重启后故障排查

第一次用新密码登录成功后,建议立刻跑几条命令确认修改没留下副作用:

last reboot systemctl --state=failed journalctl -b -u sshd

看三件事:系统是不是按预期正常引导、有没有服务启动失败、SSH 能不能正常登录。如果在 RHEL/CentOS 上选择了 autorelabel,第一次启动会慢到让你怀疑系统卡死了,这是正常的,你可以在控制台看到重新打标签的输出;但如果等很久都没有任何输出,要检查是不是 SELinux 策略导致文件系统挂在奇怪的状态。

常见故障无非两种:一种是忘了 touch /.autorelabel,重启后 sshd 等高级服务因 SELinux 标签错误起不来,报错信息里会出现 SELinux is preventing 之类的字眼;另一种是 chroot 环境下手贱去改 /etc/passwd,把 root 的 shell 或者 uid 改坏了。修复方式也很直白,用相同流程重新进去改回来。

5.2 预防下次再忘密码:备份 root 哈希与 sudo 通道

经历过一次这种操作后,你就该意识到:root 密码在团队协作环境中不能只存在于某个人的脑子里。更靠谱的做法是:

  • 把系统初始 root 密码写入内部的密码管理库,或至少放在加密的运维文档里。
  • 对于日常操作,推广 sudo 通道,让普通用户通过 sudo 执行管理命令,而不是频繁切换 root。即使 root 密码丢失,只要还有普通用户能 sudo,临时救急就会方便很多。
  • 定期备份 /etc/shadow 和 /etc/passwd 到离线位置,恢复时只需要比对文件内容或者直接 preplace 即可。

另外说个细节:Ubuntu 默认 root 账户是没有密码的,shadow 里显示为!,也就是锁定状态。管理员日常用 sudo -i 临时切换到 root。如果哪天你给 root 设置了密码,反而改变了系统的默认安全姿态,除非有明确需求,不建议长期保持 root 密码自动登录的状态。

5.3 物理安全是最后的防线

最后想认真提醒一句:本文讲的所有方法,本质上都要求你"能碰到这台机器的物理控制台"。这意味着,任何能物理接触到服务器、或者能接入 IPMI/BMC 的人,都能重置 root 密码。这不是漏洞,而是 x86 体系下引导流程的设计使然。

所以如果你的机器托管在有限的机房里,对物理访问权限的管理反而比密码复杂度更重要。对高安全要求的机器,建议做以下加固:

  • 设置 BIOS/固件密码,阻止陌生人修改启动项。
  • 在 GRUB 里配置密码保护,禁止无密码进入编辑模式。
  • 启用 SecureBoot,并对本机内核签名做校验。
  • 有条件的情况下做全盘加密(LUKS),这样即使别人拿到硬盘,也无法通过修改引导参数绕过解密层。

secure boot 和 LUKS 这套组合,能挡住绝大部分基于引导参数重置密码的攻击路径。但对应的代价是,你自己忘了密码时,恢复流程也会复杂得多,恢复时需要依赖密钥文件或恢复会话。

我在实际运维中体会最深的一点是:root 密码重置这件事,不是偶尔应急就知道怎么做的技能,而是每次都要像做变更一样写好清单。因为你可能一年只遇到一次,但每次遇到都是系统进不去、业务锁死的紧张局面,现场再去查文档只会把压力放大。把这套流程在自己的测试机、虚机上完整跑过两遍,把 rd.break 和 init=/bin/bash 的差异、SELinux 重标、MySQL 的 skip-grant-tables 窗口都亲手感知一遍,比记住任何一条命令都管用。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询