深夜接到同事求助,说服务器root密码忘了,进不去系统,数据还在但人快疯了。这活儿我一年总要干上几回,从CentOS 7到Ubuntu 22.04,从虚拟机到物理机,甚至还有嵌入式Linux开发板。今天把重置root密码这件事从头到尾捋一遍,覆盖最常见的五类场景:RHEL/CentOS 7+系列、Ubuntu/Debian系、LVM分区特殊情况、MySQL/MariaDB数据库root密码,以及嵌入式Linux设备,每一步都附操作细节和踩坑记录,照着做基本能救回来。
1. 动手前先搞清楚:root密码丢了,到底卡在哪一步
很多人一上来就搜“重置root密码”,然后对着网上一堆命令复制粘贴,结果发现根本进不去系统。这里必须先搞明白一个底层逻辑:root密码的作用,是在登录阶段验证你是谁。也就是说,系统内核和文件系统本身没有依赖这个密码,只要你能绕过登录验证、拿到shell,就能改掉它。
理解了这一点,你就会明白为什么所有重置方案都围绕一件事:启动到一种不检查密码的临时环境。在Linux里,这通常指两条路:一是通过GRUB修改内核启动参数,二是通过initramfs的调试模式。前者是老牌方法,适合几乎所有发行版;后者是RHEL/CentOS 7以后推荐的做法,因为systemd时代的单用户模式已经被弱化了。
按照要操作的平台,方案可以这样分类:
- CentOS/RHEL 7+:用
rd.break参数,进入initramfs的shell,挂载根文件系统后修改密码。 - CentOS/RHEL 6及更早:用
single参数,直接进单用户模式,不需要密码。 - Ubuntu/Debian系:GRUB菜单里选恢复模式,或者在内核参数尾加
init=/bin/bash。 - LVM分区:因为根文件系统在逻辑卷里,很多时候还要多几步lvm激活操作。
- MySQL/MariaDB:数据库系统的root密码,和操作系统root密码是两回事,重置思路完全不同。
- 嵌入式Linux:一般是busybox环境,启动参数改法类似,但存储分区可能是只读挂载。
这里提醒一句:如果服务器是云厂商买的云主机,大部分云控制台都有“重置实例密码”入口,不需要走下面这套底层操作,直接去控制台操作就行。不过云主机重置后会要求重启,生产环境记得评估重启窗口。
另外,如果你的系统开启了GRUB密码保护(也就是启动菜单都要先输密码那种),那下面的方法全部无效,你得先通过带外管理(如IPMI、iDRAC)或者联系机房处理。这个场景我放到最后的常见问题里一起说。
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. CentOS/RHEL 7+ 最快的方案:用 rd.break 破入
rd.break 是RHEL/CentOS 7开始官方文档里就认可的重置方式,流程上没有暴力痕迹,而且成功率非常高。它的原理是在initramfs阶段、根文件系统切换(switch_root)之前暂停启动流程,这时候系统还没走完完整启动流程,很多权限校验没生效,你有机会直接从内存里的临时环境对硬盘上的根文件系统动手。
2.1 前提准备:重启并按e进GRUB菜单
首先你要能物理接触到服务器,或者通过带外管理(iDRAC/IPMI/VMware控制台)打开显示器界面。然后重启服务器,在GRUB启动菜单出现时按下字母 e(不是回车),进入启动项编辑界面。
在编辑界面里,你会看到类似这样的几行内容:
bash复制linux16 /vmlinuz-3.10.0-1160.el7.x86_64 root=/dev/mapper/cl-root ro crashkernel=auto resume=/dev/mapper/cl-swap rd.lvm.lv=cl/root rd.lvm.lv=cl/swap rhgb quiet
用键盘方向键把光标移到最后一行(也就是以 linux16 或 linux 开头的那行,注意不是 linuxefi,虽然它也有效,但更推荐改linux16这行),在这一行的末尾追加一个参数:
text复制rd.break
追加完成后,按 Ctrl+x 或 F10 启动系统。系统会启动到initramfs阶段,然后停下来给一个shell提示符,大概是这样的:
bash复制Generating "/run/initramfs/rdsosreport.txt"
Entering emergency mode. Exit the shell to continue.
Type "journalctl" to view system logs.
You might want to save "/run/initramfs/rdsosreport.txt" to a USB stick or /boot
for your vendor to debug your bug.
Give root password for maintenance
(or press Control-D to continue):
这时候不要慌,这个提示虽然写了“give root password”,但你只要直接回车或者输入 Ctrl+d 继续,就会进入一个 switch_root:/# 的shell。
注意:这里有个小坑。有些版本的grub会把光标默认停在前一行,你要手动确认光标移动到了linux16那一行再改。改错行会导致参数不生效,启动流程看起来一切正常,但起来以后还是要密码。
2.2 真正的操作:挂载根文件系统,改密码
进入 switch_root:/# 后,根文件系统目前是只读挂载在 /sysroot 目录下的。先执行:
bash复制mount -o remount,rw /sysroot
然后chroot进去:
bash复制chroot /sysroot
这一步完成后,你的shell就切到了硬盘上的真实系统环境。接下来修改密码:
bash复制passwd root
系统会让你输入两次新密码,输入时不会显示任何字符,这是正常的。输入完以后会提示 passwd: all authentication tokens updated successfully.。
到这里很多人觉得完事了,直接 reboot 重启。这是最容易翻车的一步。如果你的系统启用了SELinux(CentOS/RHEL默认是强制模式),改密之后还必须执行:
bash复制touch /.autorelabel
这个文件的作用是告诉系统下次启动时自动重新给文件系统打SELinux标签。因为你在initramfs环境下改的密码,创建的 /etc/shadow 文件标签可能不对,不处理的话重启后登录阶段会被SELinux拦下来,表现为“密码明明是对的却登录不进去”。
2.3 exit退出顺序有讲究
改完之后,依次执行两次exit退出:
bash复制exit # 退出chroot环境
exit # 退出initramfs shell
按正常顺序退出后,系统会继续走完启动流程。如果创建了 /.autorelabel,系统会进入自动打标签的过程,这一步根据文件数量可能耗时5-15分钟,期间系统会反复重启一两次,千万不要在此时强制断电。
登录进去以后,建议立刻确认SELinux状态:
bash复制getenforce
如果显示 Enforcing,再检查一下:
bash复制ls -lZ /etc/shadow
正常情况应该显示 system_u:object_r:shadow_t:s0,如果标签不对,手动执行 restorecon -v /etc/shadow 修正。
提示:如果你明确知道系统之前是关闭SELinux的(
/etc/selinux/config里是SELINUX=disabled),那就不需要touch /.autorelabel。但多数人不会记得十台服务器的配置,所以我建议一律touch,最多多等几分钟,稳妥优先。
2.4 老系统如何重置:single单用户模式
CentOS 6这种老系统,或者任何仍然使用init而不是systemd的Linux,操作更简单:在GRUB启动菜单里按e编辑,找到 kernel 开头的那一行,在末尾加一个 single,然后回车启动。系统会直接以单用户模式进入一个root shell,不需要任何密码,直接 passwd 改密后 reboot。
这个方法在RHEL 7之后基本失灵,因为systemd模式下单用户模式也会要求输入root密码。所以如果你在生产环境遇到的是7以上版本,优先走rd.break方案。
3. Ubuntu / Debian 系的恢复模式:recovery + chroot
Debian/Ubuntu系的处理思路类似,但操作路径不同。Ubuntu的GRUB菜单里集成了一项 Advanced options for Ubuntu → Recovery mode,它本身就是一个不需要密码即可进入的维护环境,非常简单。
3.1 进入恢复模式
开机看到GRUB菜单后,如果屏幕只有一个紫色的Ubuntu logo,按一下 Esc 或 Shift 呼出完整菜单(老版本按Shift,新版本按Esc,两个都试最保险)。然后依次选择:
text复制Advanced options for Ubuntu
→ Ubuntu 22.04 LTS (内核版本号) (recovery mode)
系统启动后会进入一个蓝底菜单:
text复制Recovery Menu
(resume) Resume normal boot
(clean) Try to make free space
(dpkg) Repair broken packages
(fsck) Check all file systems
(root) Drop to root shell prompt
(network) Enable networking
移动到 (root) 那一项,按回车,会得到一个root shell。
3.2 关键一步:把根分区改成可写
进了root shell以后,第一件事不是急着 passwd,而是先看挂载状态:
bash复制mount | grep ' / '
你会看到根文件系统目前是**只读(ro)**挂载的。这是恢复模式故意的——避免在未确认状态时写入损坏系统。所以必须先重新挂载为读写:
bash复制mount -o remount,rw /
这里要小心一个细节:如果根分区不是单独的 /,而是 / 和 /boot、/home 都是独立分区,你还需要手动挂载其他需要的分区。通常情况下重置密码只需要改 /etc/shadow,只挂载 / 就够用了。但如果系统文件系统是LVM,恢复模式的initramfs通常已经自动激活了逻辑卷,mount -o remount,rw / 也能直接成功。
挂载成rw以后,直接执行:
bash复制passwd root
按提示输入两次新密码。如果系统有强制密码复杂度(安装了 libpam-pwquality),这里会收到一条警告,比如 BAD PASSWORD: The password fails the dictionary check。如果只是警告,新密码依然生效;如果直接报错拒绝,你就得换一个更强的新密码。
改完以后执行 exit 退出root shell,回到recovery菜单,选择 (resume) 继续正常启动。不放心的话也可以直接 reboot。
3.3 没有Recovery菜单怎么办:init=/bin/bash
有些嵌入式板子或者精简安装的Debian,菜单里根本没有recovery选项。没关系,还有一个通用方法:在GRUB编辑界面里,找到 linux 开头的那一行,在末尾追加:
text复制init=/bin/bash
然后按 Ctrl+x 启动。这样内核会直接挂载根文件系统并启动bash,而不是启动systemd。
不过这种情况下根分区大概率还是只读挂载,所以同样要重新挂载:
bash复制mount -o remount,rw /
再 passwd root 改密。这个方法需要注意的是,因为跳过了init/systemd,网络服务、设备节点这些都没起来,改完密码最好直接重启而不是尝试在这个环境下做复杂操作。
3.4 嵌入式Linux设备的root密码重置
ARM开发板、路由器、NAS这类嵌入式设备,本质思路一模一样。大多数嵌入式Linux用的是busybox,没有GRUB菜单,而是通过uboot引导。你需要在uboot启动时打断自动启动(通常是按下任意键或者特定按键),然后在uboot命令行里修改bootargs:
bash复制setenv bootargs 'console=ttymxc0 root=/dev/mmcblk1p2 rw init=/bin/sh'
boot
注意这里直接给了 rw 参数,所以进shell后不需要再手动remount,直接 passwd root 就行。如果没有uboot交互界面,只能烧录或者用串口进入调试模式,那是另一个话题了。
提示:嵌入式设备的文件系统很多是只读的(squashfs),如果根分区本身是只读设计,那
passwd会报错找不到或无法写入/etc/shadow。这种设备需要找找有没有可写的overlay分区,把/etc从overlay里重新挂载成rw,操作要复杂得多,建议先查设备手册确认overlay机制。
4. 不只Linux:MySQL / MariaDB 的root密码怎么重置
好多人在服务器上重置完系统root密码,过两天又来找我,说数据库root密码也忘了。系统root密码和数据库root密码是两套独立认证,重置思路完全不同,单独开一节讲清楚。
4.1 用 skip-grant-tables 跳过权限表
MySQL/MariaDB在启动时可以加一个参数 --skip-grant-tables,启动后不会加载权限表,任何用户都能免密登录,这个场景非常适合重置root密码。操作步骤如下:
首先停掉数据库服务:
bash复制systemctl stop mysqld # MySQL
systemctl stop mariadb # MariaDB
然后以安全模式启动:
bash复制mysqld_safe --skip-grant-tables --skip-networking &
--skip-networking 一定带上,这个参数让MySQL只允许本地socket连接,避免在这段“无认证窗口期”被网络上的其他人连进来。虽然大多数MySQL默认端口是3306且在生产网段,但谨慎一点不吃亏。
启动后,另开一个终端(或者同一个终端等shell回来后)执行:
bash复制mysql -uroot
注意不需要密码,直接回车就进去了。然后执行:
sql复制FLUSH PRIVILEGES;
ALTER USER 'root'@'localhost' IDENTIFIED BY '你的新密码';
MySQL 8.0 以上的语法要求带 IDENTIFIED BY,旧版本可以直接:
sql复制UPDATE mysql.user SET authentication_string=PASSWORD('新密码') WHERE User='root';
FLUSH PRIVILEGES;
这里有个大坑:MySQL 5.7开始已经移除了 PASSWORD() 函数,而MySQL 8.0里 authentication_string 字段存的是哈希值,不是明文。所以如果你在8.0版本上执行更新字段的SQL,一定要用 ALTER USER 而不是 UPDATE。用错的话,密码写了等于白写,下次登录直接 Access denied。
执行完以后退出mysql:
sql复制exit;
然后停掉mysqld_safe进程,正常启动数据库:
bash复制kill $(pgrep -f mysqld_safe)
systemctl start mysqld
数据库起来以后,用新密码验证一下:
bash复制mysql -uroot -p
4.2 MySQL 8 的auth_socket插件问题
如果你用的是Ubuntu默认安装的MySQL,而不是从官方仓库装的,那root用户默认认证插件是 auth_socket,它不走密码验证,而是检查当前系统用户是否为root或sudo用户。这种情况下,直接 sudo mysql 就能进数据库,压根不需要密码。很多新手会误以为“MySQL没有密码”,其实只是默认插件不同。
要改成密码登录:
sql复制ALTER USER 'root'@'localhost' IDENTIFIED WITH mysql_native_password BY '新密码';
或者用MySQL 8推荐的caching_sha2_password:
sql复制ALTER USER 'root'@'localhost' IDENTIFIED BY '新密码';
MariaDB大多默认还是 mysql_native_password,直接用上面4.1的ALTER USER就行。
4.3 密码过期与“强制改密”怎么处理
系统层面还有个常见的坑:Linux账户密码过期了,登录时提示 Password expired,强制要你改密。如果你忘了旧密码,在登录界面就直接死循环:不改密登不进去,但改密必须输入旧密码。
处理方式很简单,走任意一种root重置通道(rd.break、recovery mode都行),然后执行:
bash复制chage -M 99999 root
chage -M 后面接的是密码最长有效期天数,设为99999就基本等于永不过期。查看某个用户密码过期状态用:
bash复制chage -l root
如果只是想强制某用户下次登录时改密码,用:
bash复制chage -d 0 username
这会把用户密码的最后修改日期设为0,下次登录就会被强制要求改密,这个特性可以用来给管理员做周期性密码轮换。
5. 重置成功之后:收尾与常见问题排查
密码改好了,系统也进去了,但不代表这件事彻底结束了。有几个收尾动作和排查经验,属于“不写进官方文档但非常实用”的范畴。
5.1 立刻要做的三件事
第一件事,检查系统日志。重置密码这个操作本身有痕迹吗?有。在rd.break或者recovery模式下你改的是shadow文件,内核日志和审计日志都不会特意记录passwd命令。但你重启之后,系统的 last 命令会显示root最近登录记录,你自己心里要有数。另外如果你在串口控制台操作过,串口日志里会留下痕迹。这些不是要刻意抹掉,只是你要知道操作不是完全无痕的,对敏感环境需要提前跟同事对齐。
第二件事,检查SELinux和firewalld状态。用rd.break方式改完密码后,如果 touch /.autorelabel 了,但系统启动后你发现 getenforce 变成 Disabled 了,说明autorelabel过程把SELinux配置文件也改了(极少见但确实可能发生)。你需要确认 /etc/selinux/config 内容是否符合预期,不符合就改回来。
第三件事,检查SSH相关配置。如果你是通过SSH远程操作重置密码,重置完成后务必测试SSH能正常登录。如果系统启用了PermitRootLogin禁止root远程登录,那你重启后依然无法远程SSH登录root,需要通过普通用户su切root。这个不是bug,是安全策略,别在排查上浪费时间。
5.2 常见的五个翻车点
| 现象 | 原因 | 解决方法 |
|---|---|---|
| 重启后卡在“Starting update UTMP about System Reboot” | 创建了autorelabel但忘了等它跑完 | 强制重启一次,让autorelabel进程继续执行 |
| 改完密码还是登不进去 | SELinux标签没处理 | 重新进rd.break,手动执行 restorecon -v /etc/shadow |
| 单用户模式启动失败直接黑屏 | 系统是systemd版本,不支持single参数 | 改用rd.break方案 |
| MySQL执行ALTER USER报语法错误 | 版本太低,不支持IDENTIFIED WITH | 先 SELECT VERSION(); 确认版本,用对应语法 |
| 数据库root改完密码后客户端连不上 | 用户host匹配不止localhost | 检查 mysql.user 表,确认host字段是localhost还是% |
5.3 关于“重置密码”这件事,我的真实体会
我做过无数次root密码重置,最深的感触是:这套操作的关键其实不在命令本身,而在你对该系统架构的掌握程度。系统是UEFI还是BIOS?GRUB版本是多少?根分区是不是LVM?有没有开启SELinux?这些信息决定了同样的“重置root密码”四个字,要走的路径完全不同。所以每次我接到这类需求,第一件事永远是让对方拍一张GRUB菜单的照片,看一眼内核参数,再决定用哪套方案。
另外一个很现实的建议:重置完密码之后,顺手把密码放到团队密码管理工具里,别再依赖脑子记或者本地txt。服务器又不是只有你一个人要管,万一哪天调岗、离职、交接,密码找不到才是真正的灾难。如果你在重置过程中发现系统根本没开SSH密钥登录,建议趁这次改密的机会,生成一对新的root公钥放进 /root/.ssh/authorized_keys,下次再忘密码,至少还有一条路可以进去,不用每次都重启机器走GRUB流程。
