
1. 先说清楚密码“破解”和“重置”到底是不是一回事干运维这行谁没在半夜被一个电话叫醒过——“服务器连不上了”。电话那头口气很急你远程试了试root 密码错误再试还是错误。这时候心就凉了半截要么是哪个同事手滑改了密码没同步要么就是长期没人动密码早被遗忘在某个离职员工的脑子里了。不管哪种情况手里的远程通道一旦进不去整个人都是慌的。所以在展开所有操作之前我得先把“破解”这个词掰开揉碎讲清楚。我们在日常工作中说的“root 密码破解”绝大多数情况下并不是真正意义上对未知密码的暴力攻击而是“在物理机或虚拟化控制台可达的前提下通过系统设计好的恢复机制重新设置密码”。说直白点就是我给你一把钥匙胚教你把锁撬开、换上自己的锁芯而不是研究怎么配一把万能钥匙去开别人家的门。这两者在目的、边界和道德属性上完全是两码事。这也是为什么你搜“centos7 root 密码忘了”的时候网上铺天盖地的教程其实都是在讲同一件事进入单用户模式或者救援环境重新写一个密码。整套操作的最终效果是“密码被改了”但手段上跟真正的密码破解比如抓取密码哈希、字典碰撞、离线爆破没有任何关系。本文所有内容都基于一个前提你是这台设备的管理员合法拥有设备的物理或远程控制权只是暂时被自己的记忆坑了。另外还有一类情况也常见就是普通用户的密码忘了。平时 sudo 权限掌握在少数人手里某个开发人员离职了、某个账号被锁定了、某台测试机的 root 密码只有一个实习生知道。这时候我们需要一条清晰的恢复路径既要快又要不影响系统里的其他服务还得保证改完之后权限模型不能被搞乱。这篇文章就把这两类场景完整串一遍root 密码的重置、普通用户密码的重置顺便把数据库 root 密码MariaDB/MySQL这个高频翻车点也一起讲了。适合谁看系统管理员、运维新手、自己折腾 Linux 服务器和树莓派的玩家以及那些被数据库 1045 报错折磨到怀疑人生的开发同学。2. 重置思路全景三条主流路线的原理与选型2.1 为什么能“绕过”密码内核参数与启动流程的底层逻辑要理解密码重置必须先理解 Linux 的启动流程。GRUB 引导内核时会加载一系列的启动参数包括指定根文件系统在哪、要不要进入图形界面、网络怎么初始化等。而内核在初始化完最基本的硬件环境后会尝试挂载根文件系统然后启动 PID 为 1 的第一个用户态进程——通常就是 systemd 或者 init。这里的关键点在于PID 1 是可以被指定替换的。如果你告诉内核“别启动 systemd 了直接给我一个 shell”那系统就会在你拥有物理访问权限或控制台权限的前提下直接给你一个 root 权限的交互环境。这是因为此时系统的认证体系还没有建立起来没有用户、没有密码校验、没有 PAM 验证一切都在最小化内核态空间里运行。这就是“重置密码能成立”的根本原因密码校验发生在用户态服务层面而内核启动阶段的内核参数注入发生在校验之前。你不需要破解任何密码你只需要在正确的时机介入启动流程。这也解释了为什么 BIOS/固件密码、GRUB 密码、磁盘加密LUKS能挡住这种操作——因为这些保护机制发生在内核启动参数注入之前的更早阶段。2.2 三条路线single、rd.break、init/bin/bash在实际救援过程中最常用的有三条路线第一条是单用户模式在 GRUB 启动参数末尾追加single或s。这是一种历史悠久的传统方案早期的 SysV init 系统普遍支持。进入之后系统会运行一个最小化的 root shell但此时可能只有部分服务被启动。第二条是rd.break这是 RHEL/CentOS 7 以后推荐的方案。它会在启动早期阶段即根文件系统尚未真正切到系统里面的磁盘时插入一个 break 点把你丢进一个initramfs环境里的 shell。在这个环境里系统真正的根目录被挂载在/sysroot下面你可以在非常干净的环境里做处理。第三条是init/bin/bash直接让内核用/bin/bash作为 PID 1。这是最直接粗暴的方案适用于那些不太在意服务优雅关闭、只想赶紧把密码改掉的场景。三条路线各有特点核心差异在“进入环境的干净程度”和“需要做的额外挂载工作”。单用户模式最接近正常系统但服务启动不完整rd.break 最干净但需要 chrootinit/bin/bash 最简洁但文件系统默认可能只读。2.3 方案选择不同场景该走哪条路实际选择时我的经验是看系统版本和手头环境CentOS/RHEL 7 及其以上版本首选 rd.break因为流程标准化而且 SELinux 的坑可以靠一个.autorelabel标记轻松绕过去。CentOS 6 及更早版本直接 single 即可。Ubuntu/Debian 系统则优先考虑 GRUB 引导菜单里的 recovery mode 选项这本质上是单用户模式的一个友好封装不需要手动敲内核参数对新手非常友好。如果是不带 GRUB 的嵌入式设备、或者 GRUB 密码被人为设了那可能就要走 live CD / 系统盘救援模式通过chroot把硬盘上的根文件系统接管过来。这个方法虽然麻烦但是万能方案几乎所有发行版都适用而且还能在同一个环境里修 GRUB、修 fstab、删掉那些配错的配置。下表是我日常选路的参考逻辑场景推荐方案理由CentOS/RHEL 7rd.break 加上 autorelabel流程短、标准、SELinux 兼容性好CentOS/RHEL 6 及以下追加single参数系统支持好一行参数的事Ubuntu/Debian 桌面或服务器recovery mode 的 root shell菜单化操作省得手拼参数无法进入 GRUB / 想额外修别的文件live CD 或安装盘救援模式 chroot最灵活什么都能动磁盘启用了 LUKS 全盘加密需要先输入解密口令才能继续这类设备物理接触也没用必须材料齐全3. 实战CentOS/RHEL 7 以上版本找回 root 的完整过程3.1 一步步操作从 GRUB 到新密码我拿一台 CentOS 7.9 的标准服务器举例整个过程大概5分钟。首先重启系统在 GRUB 菜单出现的时候选中要进入的内核条目按e进入编辑模式。找到以linux16或linux开头的那一行不同版本可能写法有差异但都在开头带vmlinuz的那行。在这一行的末尾加上一个空格然后输入rd.break按CtrlX或者F10启动。系统会在挂载真正的根文件系统之前停下来进入一个 shell 提示符通常会显示类似switch_root:/#的样子。此时系统根目录是 initramfs 环境你的实际硬盘根目录被挂载在/sysroot。所以第一步是重新以可写方式挂载它mount -o remount,rw /sysroot然后 chroot 进去早期的 read-only 状态得以解除chroot /sysroot这时候如果你输入whoami输出的就是 root。虽然此时 PATH 环境变量可能不完整但/usr/bin/passwd通常可以直接调用直接重设密码passwd root输入两次新密码后还有关键一步创建 SELinux 自动重新标记的文件。如果不做这一步系统重启时可能因为文件上下文不对而导致无法正常登录甚至在登录界面循环。做法是touch /.autorelabel然后退出 chroot再重新挂载原来的只读状态并重启exit mount -o remount,ro /sysroot reboot重启过程会稍微慢一些因为 SELinux 在做全盘上下文重新标记。耐心等它跑完之后就可以用新密码登录了。3.2 两个容易踩的坑SELinux 和文件系统只读先说 SELinux。很多新手在改完密码之后重启发现两个现象一是登录页输入密码直接闪回二是出现了relabel相关的报错。原因很简单你用 chroot 环境改了/etc/shadow之后这个文件的 SELinux 上下文可能和系统预设不匹配因为 chroot 环境里不加载 SELinux 策略系统启动时会拒绝以不正确的上下文类型访问敏感文件。.autorelabel的作用就是在下次启动时强制全盘重新打标把/etc/shadow这类文件恢复到正确的上下文。这个标记文件会在重新标记完成后被自动删除不用手动清理。另一个坑是 read-only 文件系统。如果你在进入rd.break之后没有执行mount -o remount,rw /sysroot直接运行passwd会看到passwd: Authentication token manipulation error或者写文件失败的报错。这是因为 initramfs 阶段根文件系统默认是只读挂载的。有些教程只告诉你chroot /sysroot然后直接 passwd这在小版本、initramfs 行为略有差异的系统上就会翻车。所以我每次都会强调这条 remount 命令这是整个流程里最不起眼但最关键的一步。如果你喜欢更简单粗暴的init/bin/bash路线同样要注意 remount 根文件系统为可写。命令为mount -o remount,rw /然后 passwd存续逻辑跟上面一样最后通常配合touch /.autorelabel一起使用。4. Ubuntu/Debian 系recovery mode 的操作差异4.1 菜单化恢复不敲命令也能改密码Ubuntu 和 Debian 的默认 GRUB 配置里带了一个 recovery mode 菜单项。进入高级选项选择带(recovery mode)后缀的内核条目系统会进入一个服务选择界面里面有 resume、clean、dpkg、fsck、root 等选项。选择root会直接得到一个 root shell而且根文件系统已经是可写状态。这一点和 CentOS 的 rd.break 场景不同Ubuntu 的恢复模式以尽量接近正常环境的方式启动所以省去了手动 remount 的麻烦。拿到 shell 之后直接走标准流程passwd root如果你之前给 root 设置了锁定状态Ubuntu 默认 root 没有密码但也没被显式锁定只是passwd -l root的情况不同还需要先解除锁定passwd -u rootUbuntu 默认不允许 root 直接 SSH 登录这和安全机制有关但修改密码本身不影响本地登录。4.2 Ubuntu 和 CentOS 流程差异的深层原因两者差异主要来自两个地方。第一是 initramfs 的设计CentOS 的 rd.break 要你手动处理/sysroot而 Ubuntu 的 recovery mode 本身就在系统配置中明确了根文件系统要可写挂载所以体验不同。第二是服务管理模型Ubuntu 的恢复模式提供的是一个“最小服务体系”而不是单纯的 shell所以它甚至可以让你在菜单里启用网络、修复依赖包这些功能在 CentOS 的 rd.break 里是没有的。如果你的 Ubuntu 系统启动后连 GRUB 都不显示或者你手头的是云服务器需要通过 VNC 或者带外管理控制台接入那就用到另一个思路在 GRUB 编辑界面追加breakpremount或init/bin/bash参数。追加init/bin/bash后系统会跳过 systemd 直接进入 bash此时需要手动重新挂载根分区为读写然后修改密码。这种方案的好处是不依赖 recovery mode 菜单几乎所有 GRUB 环境都适用。5. 普通用户密码不是只会 passwd 那么简单5.1 忘记普通用户密码的标准恢复流程普通用户的密码重置逻辑上要比 root 简单得多因为只要你有 root 权限passwd命令几乎可以做所有事情。但这里有一个容易被忽略的反向需求如果你连 root 都没法用呢那就回到第 3、4 章的思路先通过重置 root 拿到超级权限再重置普通用户。拿到 root shell 之后重置普通用户密码的标准做法是passwd 用户名系统会提示输入两次新密码没有任何输出算正常。如果你要对非交互式环境、脚本里批量设置用户密码用echo 用户名:新密码 | chpasswd或者用 passwd 的 stdin 参数echo 新密码 | passwd --stdin 用户名注意--stdin参数是 Red Hat 系特有Debian/Ubuntu 默认不启用但你可以在 PAM 配置里开启一般不建议。跨平台批量操作时chpasswd更稳妥。5.2 忘了密码也登录不上账号过期和锁定状态的排查有时候并不是密码被“忘”了而是账号被锁定了或者密码过期了。比如安全策略要求每 30 天强制改密到期用户没改下次登录就会被拒绝。这时候与其重置密码不如先看一眼账号状态chage -l 用户名输出里有Last password change、Password expires等关键字段。如果是密码过期可以一条命令把过期时间清零、强制下次登录时修改chage -d 0 用户名设置了这一个参数之后用户下次登录会被强制要求设置新密码密码复杂度校验策略也会生效。如果账号是被管理员锁定的chage -l看不出锁定状态需要用passwd -S 用户名输出中的L代表锁定lockedP代表可用密码。解锁命令passwd -u 用户名我在实际运维中还经常遇到一种情况用户明明就在公司却说你给的密码不对。排查到最后发现是另一个管理员把该用户的登录 shell 改成了/sbin/nologin或者/bin/false密码根本走不到验证环节就被拒了。这种时候顺手检查一下/etc/passwd文件的最后一个字段非常有必要。5.3 重置之后不要忘了密码策略重置只是第一步后续的密码管理才是真正考验。生产环境我建议的规范流程是先设置一个临时密码然后强制用户下次登录自己改echo Temp123 | passwd --stdin 用户名 chage -d 0 用户名这样既保证了临时密码是管理员可控的又避免长期使用同一个弱口令。对需要审计的账号还能通过chage -M 90设置最长使用期限配合/etc/login.defs里的PASS_MAX_DAYS全局配置。另外要提醒一句永远不要在命令行里直接传明文密码给 passwd 之外的工具。虽然echo password | passwd --stdin user这种写法大家用得很顺手但它会出现在 shell 历史里。更好的是用chpasswd配合临时生成的随机密码文件用完即删。6. 数据库场景MariaDB/MySQL 的 root 密码重置实录6.1 error 1045你们最熟悉的陌生人每次听到同事抱怨“数据库连不上了报 1045”我基本都能猜到下一句是“明明密码对怎么会 access denied”。ERROR 1045 (28000): Access denied for user rootlocalhost (using password: YES)几乎成了开发环境里出镜率最高的报错之一。这个报错的意思很简单MySQL/MariaDB 的用户认证失败。常见原因有三个一是密码真的错了或者被改了二是 root 账号对应的 host 不匹配比如你用了root127.0.0.1去连但授权表里只有rootlocalhost三是 MySQL 8.0 之后默认认证插件变了旧客户端用 mysql_native_password 无法识别 caching_sha2_password。6.2 跳过错插件认证skip-grant-tables 全流程如果是密码彻底忘记了标准重置办法是跳过授权表校验。先把数据库服务停下来systemctl stop mysqld如果是源码编译安装或非 systemd 环境用service mysql stop然后启动一个跳过授权表校验的进程。老版本的常用做法mysqld_safe --skip-grant-tables 新版本 systemd 环境里可以直接改启动参数或者临时在前台起一个进程mysqld --skip-grant-tables --skip-networking 这里加--skip-networking是为了让数据库只允许本地 socket 连接避免在跳过认证的窗口期被外部请求打进来。这一点非常关键以前出过利用这种窗口期被扫库攻击的事故所以一定要记牢。此时用 root 身份直接登录不需要密码mysql -u root进去之后因为授权表已经跳过了你需要手动刷新权限表才能让后续改密生效FLUSH PRIVILEGES;然后根据数据库版本用不同的 SQL 更新密码字段。MariaDB 和 MySQL 5.7 时代常用的写法是ALTER USER rootlocalhost IDENTIFIED BY 新密码;或者UPDATE mysql.user SET authentication_stringPASSWORD(新密码) WHERE Userroot; FLUSH PRIVILEGES;MySQL 8.0 及以上PASSWORD()函数被废弃推荐直接ALTER USER rootlocalhost IDENTIFIED WITH mysql_native_password BY 新密码;这里mysql_native_password可以替换成caching_sha2_password取决于你想用哪种认证插件。如果客户端版本较老建议用前者兼容。改完之后退出EXIT;然后重启数据库服务systemctl restart mysqld用新密码测试连接不带-p时包装一个提示确认能进这步千万别省。6.3 新装环境里的“给 root 设置密码”姿势如果你是新装的 MariaDB/MySQL碰到的是“首次登录不给密码”的情况要特别注意一个流程差异。新的初始化工具比如mysql_secure_installation会引导你设置 root 密码但如果直接mysql -u root就能进去说明auth_socket插件生效了——也就是只允许通过系统 root 用户以 Unix socket 登录。在 Ubuntu 的 MariaDB 上经常见到这种情况解决方法是ALTER USER rootlocalhost IDENTIFIED VIA mysql_native_password USING PASSWORD(新密码);或者干脆创建一个专用管理账号和系统 root 解耦CREATE USER adminlocalhost IDENTIFIED BY 强密码; GRANT ALL PRIVILEGES ON *.* TO adminlocalhost WITH GRANT OPTION; FLUSH PRIVILEGES;实际经验是数据库 root 账号不要跟系统 root 账号绑定太紧。很多开发环境被删库、被入侵都是因为应用配置里写了 root 账号并给了外网访问权限。最小权限原则在这里永远适用。7. 翻车现场常见问题与排查速查表写了这么多最后把我在一线遇到的高频问题汇总成一张速查表遇到类似症状可以直接对着排查。现象可能的根因排查/解决办法进入 rd.break 后 passwd 报错 “cannot touch”根文件系统只读mount -o remount,rw /sysroot重置 root 后重启登录闪回SELinux 上下文错乱重新执行touch /.autorelabel单用户模式被要求输入密码GRUB 或系统设置了SINGLE密码保护改用 live CD 救援模式或检查/etc/sysconfig/initUbuntu recovery mode 没有 root 选项GRUB 损坏或版本不支持从 live CD 启动后 chroot 修复passwd重置成功但 SSH 登录被拒sshd 配置禁用 root 登录检查/etc/ssh/sshd_config的PermitRootLogin重启后数据库 root 密码不生效没有FLUSH PRIVILEGES或者改错了字段重新执行FLUSH PRIVILEGESMySQL 8.0 用ALTER USER数据库启动失败存在 mysqld_safe 残留socket/pid 文件冲突清理/var/run/mysqld/下的 pid 和 socket 后重启改完密码仍提示 1045认证插件不匹配更换mysql_native_password或升级客户端驱动磁盘加密LUKS导致 initramfs 阶段无法挂载根分区加密分区需要口令才能解锁输入加密口令后再进入 rd.break或从 live CD 解锁后 chrootchroot 环境里没有 passwd 命令环境变量 PATH 不完整用/usr/bin/passwd全路径或用chroot /sysroot /bin/bash -c passwd root另外再补充三个容易忽略的小点。第一很多 VPS 厂商的云服务器默认开启了 GRUB 密码保护想进单用户模式之前先登录厂商的 VNC 控制面板看能不能正常进入 GRUB 编辑界面。第二重置完密码之后建议顺手检查一下 SSH 登录日志journalctl -u sshd --since 1 hour ago | grep -i failed看有没有大量失败的连接尝试。如果服务器之前密码就泄露了改完密码只是补救措施后续该做的安全加固密钥登录、fail2ban、关机外网 22 端口一项都不能少。第三涉及到生产环境时改密码之前先把原密码哈希文件备份一份cp /etc/shadow /etc/shadow.bak.$(date %F)万一中间操作出了岔子还能回滚。这种“先备份再动刀”的习惯关键时候真能救命。关于安卓设备 root、电视盒子固件 root、免 root 导出存档这类场景原理和服务器完全不同链路更复杂、风险更高不在本文讨论范围内。日常遇到这类需求时我的建议是先评估自己是否需要真正的 root 权限很多需求比如应用数据备份、虚拟相机已经有成熟的免 root 方案没必要为了一时方便冒着变砖或数据丢失风险去动系统底层。