半夜收到前同事的消息:一台跑批任务的服务器,root密码怎么都想不起来了,业务暂时没事,但要做配置变更时必须得有管理员权限。他问我能不能“破解”一下。其实在运维圈子里,大家口中的“root密码破解”,十有八九不是电影里那种盯着终端敲几行代码就把系统攻破的场景,而是另一件事——把你自己有权限、有物理访问能力或控制台入口的设备,在忘记密码之后合法、快速地把root密码重置回来。这是一项每个搞Linux的人都该熟练掌握的恢复技能,不是灰色技巧。
本文就围绕“重置/修改root密码”这件事来写,覆盖CentOS、RHEL、Ubuntu、Debian、云服务器、虚拟机等常见场景,讲清楚每条恢复路径背后的原理,再配上实际操作步骤和踩坑记录。需要先说明一点:所有操作的前提是这台设备归你所有,或者你拥有明确的管理授权。把别人系统的密码重置掉,那属于违法行为,别碰。
1. 先判断你的处境,再决定用哪条恢复路径
很多人一听到“root密码忘了”就立刻准备重启机器、进GRUB、敲内核参数,其实路走窄了。真正高效的运维做法是先给当前处境分类,因为不同场景对应的恢复成本天差地别。
1.1 还有sudo权限的账号可用:一条命令就解决
如果系统里还留着某个普通账号,而且这个账号有sudo权限,那完全不需要重启服务器,直接登进去执行:
bash复制sudo passwd root
输入新密码,再确认一遍即可
这一条命令就是修改root密码的标准姿势。sudo会拿当前用户的管理权限去更新/etc/shadow里的root哈希值,改完立即生效,连ssh会话都不用断开,下次root登录就用新密码。如果你的普通账号属于sudo组,或者/etc/sudoers里配置了免密sudo,那连当前用户的密码都不用输。
我见过很多人在这一步卡住,是因为他们的普通账号已经没有sudo权限了,或者压根就不记得普通账号的密码。这时候才需要考虑物理控制台级别的恢复手段。
1.2 完全进不去系统,但能接触控制台或物理机
这是最经典的重置场景:服务器能开机,能进入GRUB引导菜单,但没有任何一个账号密码能用。此时你的恢复通道是“引导阶段注入参数”,让系统在初始化时不加载正常的登录认证流程,直接给你一个root shell。
前提是你必须能接触到机器的物理控制台,或者虚拟机管理界面(如vSphere Web Client里打开终端窗口),再或者云服务器的VNC控制台。如果你只能靠ssh远程连接,机器拒绝一切登录,那就只能请机房配合或走云厂商控制台通道。
1.3 云服务器和VPS:优先用云控制台的重置密码功能
很多人不知道,阿里云、腾讯云、华为云这些主流平台的控制台里,基本都有“重置实例密码”或“重置root密码”的入口。操作逻辑一般是:在实例列表里选择这台机器,点击重置密码,输入新密码,然后强制重启或按系统提示重启,密码就生效了。
好处是云厂商已经替你把引导参数、安全组、agent联动这些细节都处理好了,不需要你自己去改GRUB。缺点是有时候控制台重置要求实例必须处于“运行中”或“已停止”状态,而且重置后旧密码直接失效。这个我后面专门讲。
1.4 动手之前先确认引导方式和GRUB版本
这一步是很多新手的坑:重启后狂按键盘但没进到GRUB菜单,或者进去了找不到对应行。原因多半是没有区分传统BIOS和UEFI。
传统BIOS + GRUB时代,开机时可能会直接显示GRUB菜单;UEFI + GRUB2时代,很多Linux发行版默认不显示菜单,需要按住Shift(Ubuntu系)或Esc(部分Windows双系统机器)才能调出来。物理机上开机自检通过后快速按方向键或Shift键,虚拟机的BIOS启动画面也会有一段短暂的提示。如果你是云服务器,一般需要在VNC画面中手动切换“重启并进入GRUB菜单”时快速按Esc或Shift,这一步多试几次就有感觉了。
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. 内核启动参数重置密码的原理,搞清楚为什么有效
直接给步骤没什么意思,因为你哪怕照着做成功了,换个版本系统可能又抓瞎。先花几分钟把原理吃透,后面所有操作都一通百通。
2.1 Linux的用户密码到底存在哪里
Linux系统里,用户的密码哈希并不存在/etc/passwd里,而是存在/etc/shadow。这个文件默认只有root能读能写,每行对应一个用户,格式大致如下:
code复制root:$6$RANDOMSALT$FgL4...:19000:0:99999:7:::
第二个字段就是密码哈希,前面那个$6$表示使用SHA-512算法,$1$是MD5,$5$是SHA-256,$y$是某些新系统上的yescrypt演算法。你执行passwd root时,它会生成一个新的哈希,替换掉这一串字符。所以不管是重置还是修改,最终动作都是让内核态工具更新这个字段。理解这点后你就能明白:只要我们能获得一个能写/etc/shadow的root shell,密码就能被重置,绕不绕开密钥、SSH、登录管理器进程,其实都是路径问题。
2.2 init=/bin/bash是什么鬼,为什么它能绕过密码
正常的Linux启动流程是:内核加载 -> 启动systemd(PID 1,系统管理器) -> systemd拉起各种服务 -> 启动登录管理器或getty -> 你输账号密码。
init=/bin/bash的意思是,告诉内核:别启动systemd了,PID 1直接由/bin/bash来充当。内核会把这个shell当作系统的第一个进程来运行,而且默认就是root身份,不需要任何认证。换句话说,系统底层的根文件系统已经挂载好,但你面前是一个直接弹出的root shell,你拥有对这个系统根目录的全部控制权。
这里有个关键细节:根文件系统是以什么方式挂载的。如果挂载参数是ro(只读),那你虽然是root,但写不进/etc/shadow,执行passwd时会报只读文件系统错误。所以恢复模式下第一件事往往是把根分区重新挂载为rw,或者一开始就在内核参数里把ro改成rw。
2.3 rd.break:systemd时代更优雅的入口
如果你用的是CentOS 7、RHEL 7、Ubuntu 18.04及以上这些systemd化的系统,还有另一个机制叫rd.break。它比init=/bin/bash稍微“正规”一点:内核按正常流程加载initramfs,但在切换到真正的根文件系统之前停下来,给你一个类似救援shell的环境。此时系统还没切换到真正的rootfs,只有initramfs里的临时环境,需要手动挂载真正的根分区才能操作。
rd.break环境下,默认的“根”是一个内存盘(initramfs),里面的文件和真正的系统根分区是两回事。所以需要先mount -o remount,rw /sysroot,把真正的根分区以可写方式挂载或重挂到/sysroot,然后chroot /sysroot切进去,再执行passwd。很多新手在这步迷路,就是因为没理解/sysroot和根分区的关系。
2.4 SELinux强制模式下的autorelabel问题
RHEL/CentOS/Fedora系列默认开启SELinux,而且通常处于 enforcing 模式。SELinux会为每个文件打上安全上下文标签,包括/etc/shadow。你通过恢复模式改密码时,可能产生的新文件或上下文标签和应用上下文不一致,等系统重启后SELinux会有概率拒绝某些服务访问,严重时连登录都异常。
解决办法是在chroot后的环境里执行touch /.autorelabel,让它在下一次启动时重新为整个文件系统刷一遍上下文标签。这也解释了为什么很多人重置完密码后,第一次重启特别慢,像是在做文件系统检查——其实就是SELinux在自动relabel,这个时间跟磁盘里的文件数量成正比,别以为系统卡死了。
3. CentOS/RHEL系重置root密码的完整实操
CentOS和RHEL在服务器领域占有率极高,这个流程我两年内至少用过十几次,把每一处细节都踩过一遍之后,给你一个可以照着抄的版本。
我以CentOS 7/8/9 + GRUB2环境为例,前提是你能打开这台机器的控制台,并完成一次重启。
3.1 标准操作:开机菜单编辑内核参数,用rd.break
第一步,重启机器,在GRUB菜单出现时按e进入编辑界面。如果你的机器是UEFI引导,开机时可能需要按住Esc或Shift才能看到菜单。
第二步,找到以linux16或linux开头的那一行,它后面是内核启动参数。在这一行末尾追加一个参数:
code复制rd.break
如果你想顺带把ro改成rw,也可以在这一步直接把ro改成rw,效果是进入恢复环境后根文件系统就是可写状态,省一步命令。但为了理解更透彻,我一般习惯保留ro,进去自己再remount。
第三步,按Ctrl+X或F10启动,系统会进入一个类似switch_root:/#的shell提示符。
第四步,执行:
bash复制mount -o remount,rw /sysroot
chroot /sysroot
passwd root
让你输两遍新密码。之后执行:
bash复制touch /.autorelabel
exit
exit
第一个exit退出chroot,第二个exit退出恢复shell,系统会继续启动过程。因为有.autorelabel标记,启动时间会明显变长,耐心等待,重启完成后root密码就是新密码。
这里有个细节必须提醒:如果你没有执行touch /.autorelabel,而且系统在启动后出现了SELinux相关的登录问题,那大概率就是上下文标签没刷新。解决办法就是再进一次恢复模式,把/.autorelabel手动生成一次。
3.2 备选方案:init=/bin/bash直接落到root shell
有的老系统或特殊定制内核不吃rd.break,那就用init=/bin/bash方案。同样是开机按e,找到linux16行,把ro改成rw,再把行末尾的启动参数中追加:
code复制init=/bin/bash
然后Ctrl+X启动。这时候你会拿到一个root shell,而且因为ro已经改成了rw,不需要额外的挂载操作,直接执行:
bash复制passwd root
但有个坑:使用init=/bin/bash时,实际上是绕过了systemd的完整初始化,/proc、/sys这些虚拟文件系统可能没有挂载。如果只改密码问题不大,但如果你还想改什么配置或者要执行一些依赖/proc的服务命令,最好自己先挂一下:
bash复制mount -t proc proc /proc
mount -t sysfs sys /sys
mount -t devtmpfs devtmpfs /dev
另外,CentOS 6及更老的系统用的是单独的single单用户模式参数,进系统后不需要chroot,直接就是完整环境的root shell,步骤上更简单,但基本逻辑一样。
3.3 为什么chroot进/sysroot之后不能直接干别的事
有人会在chroot之后顺手改了一堆配置,比如网络、hostname,然后重启后发现一部分生效一部分没生效,原因在于chroot环境里没有完整的运行环境。chroot只是把进程的根目录切换成/sysroot,但你仍然运行在initramfs的残留环境里,systemd没起来,dbus、网络管理器统统不在。改密码这种依赖shadow文件和passwd命令本身的简单操作没问题,但别指望在这个环境里用systemctl restart sshd之类的东西,那是行不通的。
4. Ubuntu/Debian系重置root密码的完整实操
Ubuntu的用户习惯和CentOS不太一样:日常管理倾向于用sudo账号而不是直接用root,所以很多人安装系统时压根没给root设置密码。这时候“重置”就不只是找回密码,而是要主动给root创建一个密码。
4.1 通过GRUB编辑进入恢复shell
Ubuntu 18.04以后默认使用GRUB2,开机时如果你快速按Shift(传统BIOS)或Esc(UEFI),会看到GRUB菜单。如果没有出现菜单,也可以直接开机时按几次Shift或Esc碰碰运气。
在菜单上选中默认内核项,按e进入编辑。找到linux这一行,将ro改成rw,并在行尾追加:
code复制init=/bin/bash
按Ctrl+X启动,接下来你会得到一个root shell。因为是rw挂载,可以直接执行:
bash复制passwd root
然后重启。注意这台Ubuntu的root账号可能是处于锁定状态的,如果发现密码设置成功后登录还是报“认证失败”,可能是root被锁了,需要再进一次恢复shell,执行:
bash复制passwd -u root
解锁之后root才能正常登录。
4.2 recovery mode(恢复模式)路径
Ubuntu的GRUB菜单里还有一个“Advanced options for Ubuntu”子菜单,里面会有“(recovery mode)”选项。选中它,进入一个带蓝色背景的菜单,里面有resume、dpkg、fsck、root等选项。
选择root,会进入一个root shell。需要手动把根分区以可写方式重新挂载:
bash复制mount -o remount,rw /
passwd root
recovery mode本质上是single单用户模式的Ubuntu定制版,它默认不要求输入密码就能给你root shell,前提是你能看到GRUB菜单并修改它。
4.3 手动挂载/proc和/sys,能避免一大半诡异问题
在Ubuntu上用init=/bin/bash或者recovery mode时,如果只是改密码,一般不需要额外挂载。但如果你在改完密码后需要操作一些管理命令,比如update-grub、apt等,很可能会遇到“read-only file system”或各种找不到设备目录的报错。
稳妥的做法是在拿到root shell后先把基础虚拟文件系统挂全:
bash复制mount -t proc proc /proc
mount -t sysfs sys /sys
mount -t devtmpfs udev /dev
还有一点:Ubuntu桌面版和服务器版在这个阶段的行为不太一样。服务器版通常比较干净,桌面版因为有图形化登录管理器,改了root密码后如果仍想用图形界面登录root,需要对登录管理器做额外配置,但这个场景很罕见,普通用户建议继续用sudo账号,不要直接登录root,安全风险大。
4.4 Ubuntu上sudo用户和root密码的关系
Ubuntu默认不让你直接登录root,而是通过sudo来执行管理任务。很多人问“我sudo后执行passwd root设了密码,为什么root还是不能ssh登录?” 这多半是因为sshd配置了PermitRootLogin prohibit-password,只允许密钥登录。要允许root远程登录,必须编辑/etc/ssh/sshd_config,设置PermitRootLogin yes,然后重启sshd。但说句实话,生产环境强烈不建议开root远程登录,后续我有一节专门讲这个。
5. 云服务器、虚拟机和特殊场景的恢复姿势
本地物理机和自建虚拟机可以直接操作GRUB,但云服务器、嵌套虚拟化和特殊环境不能一概而论。
5.1 云厂商控制台重置密码的正确用法
阿里云、腾讯云、华为云的官方流程类似:登录控制台,进入ECS/CVM/ECS实例列表,选择目标实例,点击“更多”或“操作”菜单里的“重置密码”。输入新密码后,控制台会提示你选择是否“立即重启”,一般需要重启才能生效。
这里的坑有三个。
一是如果实例里装了云监控/云安全agent插件,重置密码操作实际上是云平台通过内部通道调用guest agent来完成的,如果agent异常,重置后密码可能不生效,这时需要先“初始化云盘”或修复agent才能继续。
二是控制台重置通常会直接改掉root的密码甚至同时重置GRUB密码之类的设置,所以你如果之前用密钥登录,重置密码后要重新确认密钥对还能不能用,避免把自己锁在外面。
三是部分平台要求实例处于“已停止”状态才能执行重置,这时候你得先停止生产业务,选在业务低峰期操作,然后把之后启动、验证的步骤排好。
5.2 VMware虚拟机里的重置操作
VMware vSphere或Workstation里的虚拟机,如果你想重置root密码,本质和物理机规则一样:在虚拟机设置里打开“打开电源时进入固件”或直接从VM控制台开机按Shift/Esc进GRUB。但有一个注意点:VMware默认的UEFI固件启动速度很快,不留神就会错过GRUB菜单,可以先把虚拟机设置为“启动时进入BIOS/固件设置”,或者在VM配置里延长固件启动时间。
如果你用的模板是云厂商的镜像导出的,里面可能住着出厂设置的cloud-init或定制脚本,启动后会自动重置root密码。这种环境你即使通过恢复模式改了密码,重启后也可能被cloud-init覆盖回去。解决办法是修改/etc/cloud/cloud.cfg和/etc/cloud/cloud.cfg.d/下面关于密码管理的配置,或者彻底禁用cloud-init,这一步经常被忽视。
5.3 容器场景:为什么“容器里改root密码”不是常规操作
经常有人在一个Docker容器里执行passwd root然后发现重启容器后密码又没了。原因是容器通常以镜像文件系统的方式启动,你写入/etc/shadow的修改只存在于当前容器层,容器一旦删除,改动就完全消失。最可靠的容器内密码管理方式是在构建镜像时通过Dockerfile设置环境变量或使用entrypoint脚本动态注入,而不是进容器后手动改。这一点适合建镜像的读者留意。
5.4 重置密码后顺手检查SSH登录配置
无论通过哪种方式重置root密码,操作完之后第一件要紧事是确认SSH服务能不能用新密码登录。先检查/etc/ssh/sshd_config里这几项:
code复制PermitRootLogin yes|prohibit-password|no
PasswordAuthentication yes|no
如果PermitRootLogin是prohibit-password(常见于云镜像),那root用密码永远登录不了,只能密钥登录。PasswordAuthentication如果是no,那即使密码对了也会被拦。改配置时要小心:如果想保留现状,就别说“重置root密码后能ssh登录”这样的计划,很可能被现有的安全策略拦死。
6. 重置完密码之后的“收尾”和防再犯习惯
密码重置成功只是开始,后面还有一套收尾动作。这一部分很多人会漏,等下次忘记密码时又后悔。
6.1 修改完密码的完整命令链
我习惯在重置完成后,按顺序执行下面这些命令,确保系统处于一个可控状态:
bash复制# 确认密码哈希已更新
awk -F: '/^root:/{print $2}' /etc/shadow
# 查看用户有效期信息
chage -l root
# 强制root密码在下次登录时立即过期(谨慎使用)
chage -d 0 root
# 查看登录失败的锁定记录(有些发行版用faillock)
faillock --user root
chage -d 0 root这条要慎用,它的效果是强制root下一次登录时必须改密码。如果你是通过恢复模式改完密码,然后马上正常登录系统,这个命令可以接受;但如果这台机器用来跑无人值守程序,强制过期可能会让脚本任务因为密码过期而异常。
6.2 通过login.defs把密码策略固化下来
不要在每次重置密码后都手动叮嘱别人“密码设复杂一点”,直接在/etc/login.defs里把策略写死:
code复制PASS_MAX_DAYS 90
PASS_MIN_DAYS 1
PASS_MIN_LEN 12
PASS_WARN_AGE 7
改完后,新建用户的默认密码策略会跟着变,但对存量用户不生效。对存量root用户,用chage设置:
bash复制chage -M 90 -m 1 -W 7 root
对于生产环境,建议同时启用pam_pwquality模块,让系统拒绝弱密码。CentOS系的配置在/etc/security/pwquality.conf,Ubuntu系则是/etc/pam.d/common-password里的pam_pwquality.so参数,一般需要设置minlen=12、dcredit=-1、ucredit=-1等,强制大小写字母、数字和特殊字符组合。
6.3 防止重蹈覆辙的实用习惯
我个人的习惯是,任何一台服务器交付或接手时,第一时间做三件事:
第一,把root的SSH登录权限收掉,日常运维一律用普通账号+sudo,root密码只在物理控制台或紧急场景使用。这样即便root密码泄露,攻击面也小得多。
第二,生成一对独立的SSH密钥,配置到root账号的authorized_keys里,但禁止密码登录。这样即使忘了root密码,只要私钥在手里,也可以ssh进去然后sudo passwd root快速改密,不需要跑机房。
第三,把密码和密钥存进团队的密码管理工具,比如Bitwarden、1Password或者Keepass,别再用txt文件贴在桌面上。这里我要强调一下:密码写下来不是问题,问题是明文存放的位置和分享方式。
还有一个很容易被忽略的运维细节:重置root密码后,如果系统开启了auditd审计,建议随手查一下审计日志,确认这次密码重置的时间和来源。在RHEL系里可以看/var/log/secure,在Ubuntu系里看/var/log/auth.log。毕竟安全审计里,root密码变更属于最高级别敏感操作,留个记录既是自保,也是规范化的一部分。
6.4 遇到“密码重置了但登录还是失败”的排查顺序
这类问题我在给别人远程支持时经常碰到,按下面顺序排查基本都能找到原因:
- 确认密码确实改到了目标机器的root账户上,而不是哪个容器或虚拟机里。
- 确认/etc/shadow里root这一行不是以感叹号开头。以!开头表示账号锁定,需要用passwd -u root解锁。
- 确认登录方式对应用户的SSH配置。如果本地控制台能登录、SSH登不上,问题出在sshd_config。
- 确认PAM策略没有锁定root。看/var/log/secure或auth.log里有没有“Account locked”或“Maximum login attempts exceeded”的报错,有的话用faillock --reset或pam_tally2 --reset清掉计数。
- 如果以上都正常,但你觉得登录后执行命令提示什么都权限不足,排查SELinux(getenforce)和sudo配置。
第4条值得多说一句。现在很多发行版默认启用pam_faillock或pam_tally2,连续输错几次密码会把账号锁一段时间甚至永久锁住。你在恢复模式里重置了密码,但之前的失败计数可能还留在/var/run/faillock目录下。如果重启后立即用密码登录还是被拒绝,先清一下faillock再试:
bash复制faillock --user root --reset
这是个小细节,但能省下半小时血压。
6.5 最后分享一个经验
我处理过的“忘记root密码”事件中,大约有一半以上其实本来可以完全避免,因为系统里明明还有另一个账号有sudo权限,或者云控制台一分钟就能解决。真正到了需要进GRUB恢复模式的地步,往往是因为密码记录文件丢失、前任管理员离职交接不清楚、又或者长期没人维护导致账号全部失效。
所以我现在的做法很固定:任何服务器的root密码,我不追求“记住”,而是确保它存放在一个可授权访问的密码管理库里,同时给服务器配置密钥登录。密码的作用只是应急兜底,不是日常钥匙。
另外,操作前一定确认这台机器是你能动的那台。我见过有人半夜盯着控制台,把一台正在跑业务的生产机器当成测试机来试恢复操作,结果重启后业务掉了半小时。恢复操作本质上是中断性操作,重启、切引导参数、临时关掉SELinux,这些都会造成服务不可用。先把影响范围评估好,再动手。
