多彩编程 多彩编程MZPH · CODE BLOG
ARTICLE DETAIL

文章详情

深耕前端与后端开发技术的一线实战笔记与踩坑复盘。

Linux忘记root密码?grub与rd.break十分钟重置指南

Linux忘记root密码?grub与rd.break十分钟重置指南 深夜两点机房指示灯正常闪烁但你盯着屏幕手心冒汗服务器是好的应用是好的唯独你想登录进去改一个配置时发现自己把root密码忘得一干二净。接手的旧服务器、员工离职没交接的虚拟机、长时间没用过的测试机——绝大多数运维都遇到过这个瞬间。更尴尬的是很多朋友在这时候的第一反应是完了只能重装系统了。其实完全不用慌。root密码的所谓破解在实际运维场景里并不是什么黑客手法而是利用Linux启动流程中的设计特性以合法手段重置系统自己账户的访问权。只要你有物理控制权或者平台端的授权权限一台不知道怎么进root的Linux机器从进不去到重新拿到root通常不超过10分钟而且不需要任何第三方工具系统自带的组件就够用。这篇文章我会把整套思路讲透为什么能绕开密码、grub引导编辑里那些参数到底在干什么、rd.break为什么是CentOS/RHEL 7系的王牌、云主机和加密磁盘场景又有什么特殊边界。最后再加上我多年实操里踩过的一些坑和建议。等真正遇到那天你会感谢自己今天把这篇文章看完了。1. 忘密码的本质你要做的不是破解而是绕开认证1.1 一个真实场景密码丢了工作流直接停摆先还原一个具体场景。某次接到一个帮忙任务客户的CentOS 7测试数据库服务器做迁移的时候发现没人知道root密码。原先管理员走了交接文档也没写清楚服务器上跑着Mariadb里面还有几个项目的测试库。客户第一反应是找机房帮忙重装但重装的代价是数据要导出来、环境要重新搭整个项目至少延误三天起步。当时我的做法是要了一张机房远程管理卡的临时登录权限走KVM进去重启机器在grub菜单上动手十几分钟之后root密码重置完成客户改掉密码、数据原封不动事情就结了。这类场景在运维工作里其实出现频率很高。有一种常见的误区是觉得我连root密码都不知道系统肯定也进不去进不去就什么都做不了。实际上Linux的密码认证只是在系统启动到用户空间之后由独立的登录进程完成的。在登录进程工作之前内核早就已经把系统带起来了。我们既然能站在机器旁边就意味着能干预开机流程那就有办法在认证机制启动之前插一脚。1.2 root密码认证的链路拆解login进程与shadow文件要理解怎么绕开密码先得知道root密码存在哪、什么时候校验。Linux下用户密码信息几乎都在/etc/shadow文件里一行一个用户root用户的第一行长这样root:$6$oN4Vn8sZ$HmZk...XA1:19000:0:99999:7:::密码字段以$6$开头表示SHA-512哈希$6$后面跟的是盐值再往后才是真正的哈希串。系统校验密码的方式很简单把用户输入的字符串加同样的盐做哈希和shadow里存的哈希比对一致就算通过。这个校验动作是由登录进程触发的。传统SysV init体系下是gettyloginsystemd时代则是getty服务启动后由login程序来询问密码。也就是说在登录进程运行之前整个系统不会对你是不是root这件事做任何校验。所以我们只要做到一件事在login进程跑起来之前拿到一个能执行命令的shell而且这个shell是以root身份运行的——剩下的就是改shadow重置密码。这就是所有相关恢复方案的根本逻辑。1.3 为什么单用户模式能绕过密码不经过独立的login认证Linux从内核态切到用户态时会启动第一个进程PID 1。如果启动参数里告诉内核我要进入单用户模式那么PID 1可能直接变成/bin/sh或者一个精简的rescue目标它不会启动完整的登录服务而是直接给你一个root shell。你可以把单用户模式理解为一个带shell的最小系统文件系统挂载、一些核心设备节点准备好但网络服务、多用户会话、图形界面统统不启动。因为多用户登录还没开始认证逻辑自然就没机会执行。你能直接在这个shell里做任何管理员操作。这也是为什么单用户模式重置密码成为老运维都懂的基本功。它本质上不是去破解某个加密算法而是巧妙地选择了系统启动链路里的一段空窗期——系统还没问你你是谁就已经把你当成管理员接待了。1.4 本文定位与使用边界说句要紧的下面所有操作用途只有一个——对自己拥有合法管理权限的机器进行密码恢复。自己公司的服务器、自己负责的虚拟机、用户授权过的设备都算合理场景。如果是未经授权的系统那就不是我该教的事也请你自己对后果负责。另外我主要讲的是物理机、虚拟机这类标准Linux发行版场景因为实际高频踩坑的就是这些。至于安卓刷机root、电视盒子root、免root工具这类跟我说的root密码不是一个概念本文不会展开第五部分我会简单解释为什么它们不能混为一谈。2. grub引导编辑最通用的重置主线2.1 进入grub菜单并编辑内核启动参数grub是绝大多数Linux发行版默认的引导器。开机或重启后在grub菜单出现之前你需要中断自动启动流程。不同机器进入grub菜单的方式略有差别但主流习惯是发现grub界面有倒计时的时候直接按键盘上的E键进入编辑模式。常见套路是开机时一直点按Esc或Shift让grub菜单稳定显示出来然后光标选中默认条目按E。注意一定不要在倒计时结束前松手否则系统就正常启动了。进入编辑界面之后你会看到一串启动参数里面一定有以linux或linux16开头的一行这就对应内核镜像以及内核启动参数。我们接下来的所有操作目标都是在这一行上进行修改。2.2 在linux行追加single或init/bin/bash的原理要在登录前拿到root shell从内核启动参数上动手最直接。常用的两个参数是single或者数字1告诉systemd/init以单用户模式启动直接进入root shell。init/bin/bash更高一层让内核把第一个用户进程PID 1直接替换成bash。系统会跳过init脚本和服务管理器起步就是一个安静的root环境。两者区别在于single模式下init进程仍然执行了一部分初始化动作比如挂载文件系统所以出来后你直接就在正常root文件系统里而init/bin/bash模式下系统初始化做得很少很多文件系统可能都没挂载你需要手动处理。我个人的习惯是优先用single它最接近系统原生的单用户语义文件系统挂载情况也最完整。init/bin/bash适合系统服务有问题、连single都进不去的情况作为备用手段。2.3 逐行走一遍完整重置流程CentOS 7/8 通用下面以CentOS 7/8为例写一遍我每次都用的标准操作。CentOS 6时代大同小异RHEL系完全通用。第一步grub界面按E进入编辑。第二步找到linux16CentOS 7或linuxCentOS 8/9开头的那一行把行尾的rhgb quiet删掉或保留都无所谓关键是追加single有的版本直接加1也行。改完后的启动行末尾大致长这样linux16 /vmlinuz-3.10.0-1160.el7.x86_64 root/dev/mapper/centos-root ro crashkernelauto rhgb quiet single第三步按CtrlX或F10启动。系统会开始引导几秒钟后掉进一个root shell提示符通常是#结尾没有任何登录步骤。第四步在shell里先确认根分区挂载状态mount | grep / 如果显示的是ro只读你需要重新挂载为可写mount -o remount,rw /接下来直接修改密码passwd root输入两遍新密码。然后检查一下SELinux标签相关的问题见2.5没有异常就输入reboot -f强制重启系统恢复正常启动。重启后用新密码登录root整个恢复流程完成。从grub按E开始到能登录大多数机器5分钟之内能走完。2.4 为什么必须处理ro/rw不改就进坑很多人第一次做这个操作时栽在一个细节上shell是进去了passwd也运行了也能输入新密码但每次重启之后密码还是旧的。原因就是root文件系统当时挂在只读状态下/etc/shadow根本写不进去passwd命令表面提示成功实际什么都没落盘。进入单用户模式时grub的启动行里默认有一个ro参数意思是以只读方式挂载根文件系统。这个设计原本是为了安全防止启动阶段意外写坏根分区但做密码重置恰恰需要写shadow所以必须手动把挂载权限改回来。两种改法在grub编辑时直接把启动行里的ro改成rw这样系统挂载根文件系统时就直接是读写的进shell后不需要再执行remount。先不动grub参数进shell后再执行mount -o remount,rw /效果一样。我个人推荐在grub编辑时顺手把ro改成rw少一次操作后续还不用担心某些系统init脚本以只读方式提前做一些事。提示如果进shell后发现还是只读不要反复尝试passwd先用touch /testfile验证能否写入不行就remount否则白忙活。2.5 SELinux的re标签问题CentOS 7专属坑CentOS/RHEL 7以上默认开启SELinux密码重置里一个非常隐蔽的坑就在这里。当你修改/etc/shadow之后文件的SELinux安全上下文可能变了。正常情况下/etc/shadow的上下文应该是system_u:object_r:shadow_t:s0而你在单用户模式那种特殊环境下改文件它可能被重新打上了别的标签比如root_t或者unconfined_t。后果是什么重启之后系统可能仍然不让你登录——不是密码不对而是SELinux拒绝所有程序读取那个标签错乱的shadow文件。很多人在这一步误以为密码没改成功反复重置好几遍纯粹浪费感情。规避方式很简单改完密码后顺手执行touch /.autorelabel这个文件存在的意义是让系统在下次启动时自动对整个文件系统做一次SELinux标签重写。会有一定性能开销取决于磁盘大小可能需要几分钟到几十分钟但至少不会卡在登录环节。如果你不想触发全盘relabel也可以用restorecon -v /etc/shadow只修正这一个文件的上下文。我在生产机器上通常选择restorecon -v /etc/shadow生效快不拖累启动时间。只有不确定哪些文件被动过时才用touch /.autorelabel兜底。3. rd.break方案dracut时代的另一种选择3.1 rd.break是什么触发的是哪一层shellrd.break是dracut框架留给运维的调试入口。dracut负责生成initramfs在真正的root文件系统挂载之前内核对initramfs做一次预加载这里面有一套属于自己的精简shell环境。你在grub启动行加上rd.break后系统会在initramfs阶段停下来给你一个比单用户模式还要早的shell。它的位置在核心技术链路上比单用户模式更靠前单用户模式是root文件系统已经挂好、init进程完成初始化之后进入的rd.break时root文件系统根本没有挂载你实际上是在内存里的initramfs环境中操作。也因此rd.break能解决一些单用户模式进不去的情况。比如某些系统损坏后根文件系统挂载失败直接进single会卡住但在rd.break里你还能手动排查、把该做的检查做了再继续。3.2 CentOS 7/8 RHEL的完整操作rd.break在CentOS 7/8上操作路径非常稳定。步骤如下grub菜单按E编辑在linux16或linux行末尾追加rd.break然后按CtrlX启动。系统会走到dracut shell提示符类似switch_root:/#。此时root文件系统其实已经分配好设备但还没正式挂载到/sysroot上。你需要主动挂载mount -o remount,rw /sysroot这条命令的意思是把/sysroot重新挂载为可写。有的教程会写mount /dev/mapper/centos-root /sysroot但CentOS 7实际环境里/sysroot往往已经被只读挂上了所以标准动作是remount。然后切进真实的root文件系统chroot /sysroot这一步等于把操作环境换根到硬盘上的真实系统里。之后你就在真实系统里改密码passwd root照例处理一下SELinux标签问题touch /.autorelabel最后退出chroot和dracut shell让系统继续引导exit exit reboot -f第一个exit退出chroot回到switch_root:/#提示符第二个exit告诉dracut我完事了系统会继续后续初始化流程。如果你在rd.break里动了什么不该动的第二个exit之后系统报错一般还是能起来只是过程会别扭一点。3.3 chroot前为什么要挂载和read-write有一个高频问题是为什么要先remount再chroot不能直接chroot吗因为chroot只是把根目录切换到另一个路径它不负责文件系统的挂载和读写权限。如果/sysroot还是只读状态你chroot进去之后执行passwd root回到和2.4一样的坑写不进shadow密码改了个寂寞。先remount保证底层块设备可写chroot进去才能正常工作。同理有的教程会让你在rd.break里直接对/sysroot/etc/shadow操作。理论上可以但我不建议因为你还要处理一些挂载关系比如/dev、/proc一旦操作复数文件路径很容易蒙混。chroot之后就是一个逼真的正常系统环境用什么命令和平时习惯完全一致减少低级错误的概率。3.4 对比grub single / rd.break / rescue.target的适用场景单用户模式也好rd.break也好本质都是拿到root shell但切入时机不同适用场景也不同。我按实际经验总结了下方式进入阶段适用场景注意点grub追加single用户空间早期密码遗失系统本身健康需要能处理SELinux标签问题grub追加rd.breakinitramfs阶段根文件系统挂载异常、systemd故障需手动挂载/remount /sysroot追加systemd.unitrescue.targetsystemd早期与single类似systemd版本依赖性更低CentOS 7生效需登录密码则绕不进去第三条我单独说一句。systemd时代还能用systemd.unitrescue.target或systemd.unitemergency.target这两个是systemd自带的救援/紧急目标概念上类似single但某些版本下rescue.target会要求输入root密码systemd认为你可能需要认证那就不适合密码重置场景了。这就是为什么多数教程宁可让你加single也不推荐rescue.target——single在某些配置里同样不会跳过认证但实践上踩中要求认证的概率小一些。我给的建议是进了shell先id看一眼确认是uid0(root)再干活如果是普通用户权限就得换方案。4. 高级场景加密磁盘、云主机、容器、Ubuntu recovery4.1 Ubuntu/Debian的recovery mode和root shellUbuntu/Debian和CentOS在引导方式上有差异。Ubuntu的grub菜单里通常自带一个Advanced options for Ubuntu子菜单展开后能看到带(recovery mode)字样的内核条目。选中它系统会进入一个简单的恢复菜单其中就有root选项选它就能直接进root shell。如果grub菜单里没有recovery选项也可以手动编辑按E进入编辑找到以linux开头的行Ubuntu 18.04通常是linux /boot/vmlinuz-... root... ro把结尾的ro改成rw quiet splash后面加single或者直接替换ro为rw init/bin/bash。保存启动后一样能落到root shell。Ubuntu有一点值得提醒因为默认没装SELinux用的是AppArmor你不需要担心2.5里说的SELinux标签问题。但Ubuntu 22.04的一些系统可能启用systemd对root的某些限制遇到奇怪问题先检查系统版本再排查方向。4.2 LUKS全盘加密时的边界如果你的磁盘做了LUKS全盘加密问题性质会变引导过程中系统会在initramfs阶段要求输入LUKS的密码来解密磁盘。单用户模式也好、rd.break也好都不影响这一步——解密对任何人都是必答题包括root。这意味着什么如果你只是忘了root密码但还记得LUKS密码上面所有方法照常能用在grub编辑后系统会让你输入LUKS密码完成解密然后继续进入shell。如果你连LUKS密码也忘了那就不是引导参数能解决的范畴了需要LUKS密钥文件、备份头信息或者从另一个有权限的系统里去恢复密钥。这个复杂度已经完全是另一个量级多数企业和个人的选择是如果LUKS密码和root密码一起丢且没有密钥备份数据基本只能认命平时一定要把LUKS密码和恢复密钥文件留在可信的地方。所以做密码重置前先搞清楚这台机器是不是有加密盘。进grub编辑后如果系统停在请输入密码之类的位置别浪费时间折腾引导参数老老实实把LUKS密码找出来。4.3 云主机控制台重置与救援镜像云主机阿里云、腾讯云、AWS EC2等很少需要用grub编辑这套因为云平台都提供了更优雅的路径大多数云厂商的控制台有重置密码功能直接重置后重启即可。不方便用控制台重置的可以用救援模式关机后挂载一个救援系统通常是厂商提供的最小Linux发行版把原系统盘挂载为数据盘用chroot进去改密码思路跟rd.break里的chroot一模一样。另外提醒一个云上特有的坑云主机默认grub等待时间可能极短0秒秒进内核你根本没机会按E。要远程进入grub编辑得通过云厂商的VNC/控制台连接并且需要在操作系统启动参数里开启grub的菜单延时。如果你就是想在云主机上用引导法可以先试试在grub界面疯狂按Esc有些云厂商镜像是保留了菜单的。4.4 容器内root密码重置docker exec直接进去容器场景则简单得多。容器没有独立的内核和引导过程root密码重置根本不需要碰grub。如果你有宿主机和Docker的权限直接docker exec -it 容器名 bash进去之后passwd root改完退出即可。如果容器里没有bash用sh如果容器里甚至没有passwd命令也有替代思路——比如挂载数据卷到宿主机直接编辑对应目录下的etc/shadow前提是你理解那个容器的认证逻辑。很多容器镜像是基于精简系统做的默认root密码就是不存在使用密钥或免密登录你要做的不是重置而是设置。这种处理同样简单docker exec进去用passwd root设置即可。4.5 电视盒子/安卓等消费设备的root为什么不在讨论范围热搜词里能看到大量电视盒子root安卓11免root导出存档红米k70 root工具之类的条目。这里说清楚安卓类和嵌入式Linux设备的root跟服务器的root密码重置完全是两码事。安卓系统的root本质上是往系统里植入su二进制、修改boot分区或者刷入专门的内核让应用层拿到root权限电视盒子类似的root固件也是在操作boot和分区。它们大多数没有grub安卓用bootloader电视盒子用原生引导也没有传统的/etc/shadow登录认证。想用grubpasswd这套去处理安卓手机方向是完全错误的。另外手机root、盒子root还牵扯到系统完整性校验、厂商保修政策一旦操作错误很容易变砖。如果你手里正好是这类设备的root权限需求应该去看对应机型的第三方社区方案而不是看Linux服务器密码重置教程。本文涉及的场景只到标准Linux发行版为止。5. 改完密码之后检查、加固、别再忘5.1 改完别急着离开回头看认证日志密码改完、机器正常能登录很多人觉得大功告成直接闪人。但我不建议这么做——你接手了一台没人知道root密码的机器谁知道它在无人值守的这段时间里有没有被动过重置密码只是拿回控制权接下来应该花10分钟做体检。先看登录记录last -x | head -50 journalctl -u sshd --since 30 days ago | grep -i accepted journalctl _COMMlogin --since 30 days ago重点看有没有你不认识的IP、异常时段的登录记录。如果发现可疑条目别急着改密码了先查后门。查SSH信任关系cat /root/.ssh/authorized_keys这里是最容易被做手脚的地方——对方可能往root的authorized_keys里塞了一把公钥这样即使不改密码也能随时登进来。你重置密码这种事根本防不住公钥登录。发现可疑key直接删除。还有静态检查cat /etc/passwd | awk -F: $30{print $1 $3}正常情况下只有root的UID是0如果看到其他用户也以UID 0存在说明有人创建了隐藏管理员账户需要马上处理。5.2 可执行文件/服务层面的后门检查另外要看系统服务和计划任务因为有经验的手脚不会只放在账号层面ls -lt /etc/systemd/system/*.service systemctl list-units --typeservice --staterunning cat /etc/crontab ls -la /etc/cron.d/ /var/spool/cron/以及/usr/local/bin、/usr/local/sbin这类目录下的可疑二进制ls -lt /usr/local/bin/ | head -20如果这台机器是你自己的这些检查可能看着多余但如果是接手一台长期无人认领的服务器这一步绝对不能省。我踩过最深的坑就是在某台闲置机器里发现定时任务每天半夜向外传输数据——那台机器的root密码早在半年前就已经被人换过了。5.3 让密码不容易忘的落地措施给自己省点事下面三个措施能直接降低再犯概率第一配置SSH密钥登录。真正进入生产环境后依赖密码本身就是高风险习惯。至少把root的SSH登录改成仅允许密钥控制台本地密码作为紧急预案保留即可。第二密码策略不要追求不可能被猜要追求你一定能想起来。我见过太多人给自己设了一个记不住的root密码然后写在小纸条上贴在显示器下面——这比密码简单还蠢。合理做法是用一个长短语比如S1eepNight#2025!这种自己能关联记忆的或者直接交给密码管理器托管。运维工作中的root密码不该只有一个人知道至少要有一个搭档或一个加密的密码库。第三每次做系统交付时把root密码写进交接文档并且注明此密码为初始密码交付后请立即更改。从流程层面杜绝人走了、密码也带走了的情况。5.4 顺手处理关联的数据库root密码热搜词里有个给mariadb root设置密码这提醒了我一个重要关联项很多Linux机器上还跑着MySQL/Mariadb数据库的root用户和系统root用户是两套独立的认证体系。很多人重置完系统root密码就完事了但数据库的root密码可能是另一串不知道的字符串。这会导致一个很有意思的情况你虽然能进系统了但数据库管理后台登不进去业务照样起不来。处理方式取决于环境。如果数据库root密码也遗失了你可以用数据库自身的skip-grant-tables模式启动来重置比如systemctl stop mariadb mysqld_safe --skip-grant-tables 进去之后执行ALTER USER rootlocalhost IDENTIFIED BY 新密码; FLUSH PRIVILEGES;注意这种临时启动方式只允许本地短时间使用操作完立刻正常重启数据库服务别留着一个无认证的实例在跑。数据库密码和系统密码分开保存这个习惯养成之后未来的麻烦会少一大截。我在实际操作中还有个习惯密码重置完成后如果机器上有任何还在跑的业务进程一定抽空安排一次业务方参与的验证窗口因为密码重置这个动作本身一般不影响运行中的服务但后续任何一次重启都可能导致它们依赖的某些环境变量或密钥失效。也就是说改密码不难改完之后让所有依赖它的环节都明确知道这次改过了才叫真正做完。
返回列表