凌晨两点,你刚在服务器上改完sshd配置,手一抖把会话断了,重新登录却发现密码怎么输都不对——再一查,root密码好像也被你忘得一干二净。这种时刻我经历过不止一次,我的第一反应曾经是“完了,只能重装系统”,但后来自从搞懂了Ubuntu的root密码机制,才发现根本不用走到那一步。这篇文章就专门聊Ubuntu下root密码忘了该怎么处理:哪些情况其实不用重置密码、恢复模式和init=/bin/bash两种快捷方案的完整操作、Live USB兜底改法的步骤,以及改完密码之后必须处理的一堆收尾细节。无论你是服务器运维、刚转Linux的开发,还是自己折腾Ubuntu桌面机的爱好者,这套流程都适用。
1. 动手之前先分清:你忘的到底是哪个密码
1.1 Ubuntu默认没有root密码,这是设计不是坑
很多从CentOS、Windows转过来的朋友都会在Ubuntu上卡第一个跟头:装系统的时候根本没让设置root密码,只设置了一个普通用户,然后装完发现su -输啥都不对。这不是你记错了,是Ubuntu默认就把root账户锁死了。安装过程中创建的那个用户,密码只对那个用户有效,root那边压根就没有可用密码——/etc/shadow里root那一行是!开头,意为锁定。
这个设计和Debian一脉相承:日常管理用sudo,root身份通过sudo临时获得,避免长时间用root在系统里裸奔。所以你“忘记root密码”时,先不要急着去改东西,先问自己一个问题:我平时真的是用root登录吗?如果答案是否,那你需要的可能不是“重置root密码”,而是“重置那个sudo用户的密码”——两者操作路径完全不同,下文会分开讲。顺带一提,热搜里经常看到“linux把普通用户变成root”,其实指的就是把普通用户加入sudo组:usermod -aG sudo 用户名,这跟“忘记root密码”是两码事,别混。
1.2 三种常见“密码失效”场景的自查方法
我列一下实际工作中最常见的三种情况,你可以对号入座。
| 场景 | 现象 | 需要的操作 |
|---|---|---|
| sudo用户密码忘了 | 登录时输密码进不去,或sudo提示输密码总报错 | 进恢复模式,用root权限重置普通用户密码 |
| root密码忘了/未设置 | su - 提示认证失败,但普通用户还能登录 | 进恢复模式,passwd root即可 |
| 密码过期被锁 | 登录后强制要求改密码,或提示account is expired | 用chage重置过期时间,而不是单纯改密码 |
这里特别说一下第三种。很多人以为“密码过期”和“密码错误”是一回事,其实两个概念。Ubuntu的密码策略在/etc/login.defs里配置,如果PASS_MAX_DAYS被改小了,或者有人手动用chage设置了密码有效期,到期后账户就会强制你改密码。SSH登录时遇到Your password has expired属于这种情况,交互式界面会引导你改密码,但如果你用自动化脚本或某些客户端连上去,可能直接卡死。判断方法是登录后看chage -l 用户名输出的“Password expires”字段。
如果你能登录普通用户,只是sudo输密码不对,那基本没救,因为sudo要密码,sudo passwd 用户名这条路也被堵死。如果手里还留着一个root shell会话,什么都好说;如果会话也断了,那就老老实实走下面的恢复流程,别想着绕。
2. 首选方案:从GRUB恢复菜单重置密码
2.1 怎样顺利进入GRUB菜单
这一步是整个流程里最容易翻车的地方,很多人栽在“进不去恢复菜单”上。原因是Ubuntu默认单系统安装时,GRUB菜单在引导时根本不显示,黑屏一闪就进系统了。
我的经验是:开机后盯着屏幕,在BIOS自检画面那段快速连按Shift键(传统BIOS机型),或者狂按Esc/左侧Shift(UEFI机型)——具体哪个键跟主板固件有关,可以都试。时机大概在“固件logo消失、内核开始加载”之前那个窗口期。如果你装的是Ubuntu和Windows双系统,GRUB菜单默认会出现,反倒不用纠结。
还有一个土办法:如果你实在掌握不好时机,可以在Ubuntu里先用sudo systemctl reboot --firmware-setup进BIOS,把启动模式或启动顺序调整一下,让GRUB多停留一会儿;或者重启时按住Shift不放,从开机一直按到GRUB菜单出现,总有一个时刻能拦住。UEFI的Secure Boot目前一般不影响这个操作,但如果你开了,记住恢复模式下某些第三方驱动可能加载不了,这不影响passwd。
2.2 进入root shell后的关键操作
GRUB菜单出来后:
- 选择
Advanced options for Ubuntu(高级选项) - 在展开的列表里挑一个带
(recovery mode)字样的内核条目 - 进入恢复菜单后,选
root - Drop to root shell prompt(跳到root shell) - 此时你已经有了root权限,但文件系统以只读方式挂载
这里有个关键点:恢复模式的root shell,默认把根文件系统以只读方式挂载。直接跑passwd root大概率报错,因为passwd需要写/etc/shadow。所以第一步一定先执行:
mount -o remount,rw /然后再改密码:
passwd root如果你要重置的是普通用户(比如忘了ubuntu这个用户的密码):
passwd ubuntu改完直接reboot重启,新密码立即生效,不需要额外操作。整个过程大概一分钟,是我处理这类问题时的首选方案。
2.3 为什么文件系统是只读的,以及不处理会怎样
我第一次用恢复模式时,直接输passwd root,然后看到passwd: Authentication token manipulation error,当时完全懵。后来想明白,恢复模式只读挂载是为了在系统异常时保护文件系统不被意外写坏——你就想成一个外科医生做手术前先把患者固定好,防止操作时乱动。
如果你忘了remount这一步,系统会明确告诉你操作失败,/etc/shadow里写不进内容,但不会损坏什么东西,所以不用慌。要注意:mount -o remount,rw /只对当前根分区有效。如果你的/boot或其他关键分区是独立挂载的,通常不影响passwd,因为shadow文件在根分区上。
还有一个细节:恢复模式下/proc这些虚拟文件系统一般已经挂好了,passwd的PAM认证流程基本能跑通。但如果你在那个shell里发现各种奇怪的报错,比如passwd: PAM authentication failure,先检查mount | grep /proc,如果没有输出就补一句:
mount -t proc proc /proc这个问题在后面的init=/bin/bash方案里更常见,恢复模式下一般碰不到,但知道了就能快速定位。
3. 恢复菜单失灵时的备选:内核参数init=/bin/bash
3.1 手动编辑GRUB启动项的具体操作
有时候恢复模式会出幺蛾子:菜单能进,但选了root - Drop to root shell prompt之后直接黑屏、卡死,或者shell起不来。这种时候我一般改用内核参数大法。
启动时在GRUB菜单界面按e进入编辑模式。找到以linux开头的那一行(UEFI的老版本里可能是linuxefi),这一行很长,包含很多内核参数,比如quiet splash之类。把光标移到行尾,先删掉可能引起麻烦的quiet splash(这两个参数只是隐藏启动日志,不删也没事),然后在行尾加:
init=/bin/bash按Ctrl+X或F10启动,系统会跳过正常的init流程,直接给你一个真正的bash。这个bash是root身份,没有密码拦截,相当于直接拿到了系统最高权限。
3.2 进入bash后的完整命令序列
这个bash环境和恢复模式不一样,它非常“裸”——文件系统只读、没有网络、没有正常服务,虚拟文件系统也没挂。所以命令顺序很重要,我踩过坑,按下面这个顺序来基本不会翻车:
mount -o remount,rw / mount -t proc proc /proc mount -t sysfs sysfs /sys passwd root在只读状态下passwd会报错,这个前面说过。挂/proc是因为passwd走的PAM模块需要读取系统信息,不挂可能会有诡异报错,虽然有时不挂也能跑,但既然都进到这里了,顺手挂上不亏。
改完密码后,直接reboot不一定行,因为正常关机流程被跳过了,我遇到过reboot命令没反应的情况。稳妥做法是:
exec /sbin/init这条命令会恢复正常启动流程,让系统带着改好的shadow文件正常起来。如果exec /sbin/init也卡住,那只能长按电源键强制重启,再开机一般没问题,毕竟密码已经落盘了。
3.3 这个方案的差异与限制
两者本质都是拿root shell,但差异很实在:
| 对比项 | 恢复模式 | init=/bin/bash |
|---|---|---|
| 环境完整度 | 迷你服务环境,/proc /sys已挂 | 极简环境,需手动挂载 |
| 适用场景 | 系统能启动,GRUB正常 | 恢复模式起不来、菜单异常 |
| 操作风险 | 低,参数现成 | 中,手动编辑内核参数 |
| 对加密盘 | 仍需LUKS密码 | 仍需LUKS密码 |
init=/bin/bash方案有个大前提:你的系统盘没有整盘加密。如果装了LUKS全盘加密,进GRUB编辑界面后、内核真正加载前,系统会先要求你输入密码解锁硬盘。如果这个密码也忘了,那上面所有方案全部失效,只能走Live USB方案,并且在Live环境里同样需要LUKS密码才能解开——如果连LUKS密码都没了,那真的只能格式化重装了,这个要有心理准备。
另外,如果系统装了SELinux(Ubuntu默认是AppArmor,基本不受影响),从init=/bin/bash环境改完密码后,SELinux文件标签可能错乱,需要额外做touch /.autorelabel再重启。Ubuntu用户不用管这个,但如果你曾经手动换过SELinux,或者用的是其他发行版,这个坑要记住。
4. 最稳妥的兜底:Live USB + chroot改密码
4.1 用U盘进Live环境的准备工作
前面两种方案都依赖GRUB和内核能正常启动。如果GRUB坏到连菜单都出不来,或者系统完全开不了机,就该动用最后手段:用另一台电脑做一个Ubuntu Live启动盘,从U盘启动系统,然后在Live环境里把硬盘挂载起来,chroot进去改密码。
做启动盘很简单:到Ubuntu官网下载对应版本的ISO,用dd写入U盘(Windows上可以用Rufus、balenaEtcher)。注意Live环境的版本最好和硬盘里的系统大版本一致,比如硬盘是20.04就用20.04的Live盘,避免因为版本差异带来不必要的变量。
从U盘启动后选择“Try Ubuntu”进入Live桌面。打开终端,第一件事是看清硬盘分区:
sudo lsblk -f对比分区列表里的文件系统类型和大小,找到你的根分区。常见的命名:/dev/sda1、/dev/nvme0n1p2之类。如果你的系统是LUKS加密的,lsblk里会看到一个叫crypt或LUKS的设备,需要先解密:
sudo cryptsetup luksOpen /dev/sda2 cryptroot会提示输入LUKS密码,输入后生成/dev/mapper/cryptroot,这就是逻辑上的根分区,后面mount都对这个设备操作。
4.2 chroot环境下的密码重置与账户解锁
找到根分区后,按顺序执行:
sudo mount /dev/sda2 /mnt sudo mount --bind /dev /mnt/dev sudo mount --bind /proc /mnt/proc sudo mount --bind /sys /mnt/sys sudo chroot /mnt/dev、/proc、/sys这三个bind mount是重中之重。chroot进去之后,如果不挂这些目录,很多命令会直接失败。我的理解是:chroot只是把根目录换了,但内核提供的设备节点、进程信息、系统状态接口还在原来的全局位置上,bind mount把它们“搬”到新根目录里,让程序以为自己在正常系统里运行。
进入chroot后就是熟悉的操作:
passwd root如果要改普通用户:
passwd ubuntu还可以顺手检查root账户锁定状态:
passwd -S root输出里P表示有密码可用,L表示锁定,NP表示没有密码。如果确认是锁定的,用passwd -u root解锁。完成后退出来:
exit sudo umount -R /mnt sudo reboot整个过程中,最容易被忽略的是:如果你之前用桌面文件管理器打开过硬盘分区,系统可能已经自动挂载了,再mount到/mnt会报already mounted,先sudo umount /dev/sda2让系统松手,再重新挂。这类“顺手连error都懒得看”的小问题,比我预想中更容易卡住新手。
4.3 遇到“设备忙”和设备名搞错的处理
chroot方案最常卡在两个地方。
一是umount时报target is busy。多半是终端当前工作目录还留在/mnt里,先cd /退出去再卸载。或者你chroot进去之后忘了exit,另开了一个终端窗口在操作,所有相关终端都关掉再卸。实在卸不掉就sudo umount -l /mnt强制延迟卸载,反正要重启,没事。
二是搞错设备名。现在很多新机器是NVMe固态,设备名是/dev/nvme0n1p1这种,而不是老式的/dev/sda1。千万别凭印象猜,lsblk -f会列出所有分区的UUID、文件系统类型和大小,按输出选准没错。如果挂错了分区,比如把/boot挂成了根分区,进去后可能看到一堆内核文件而不是/etc/shadow,这种情况立刻umount重新选。
三条路线到这里就齐了。真遇到问题,我的选择顺序是:恢复模式优先,其次init=/bin/bash,最后Live USB。前面两个快但依赖环境完好,Live USB慢但胜在什么都能救,包括顺手备份数据。
5. 密码改好后的收尾与日常防坑
5.1 顺手把root账户的锁定状态理清楚
既然费了这么大劲拿到root shell,我建议除了重置密码,顺便看一眼root账户的整体状态,避免下次再出毛病。
passwd -S root chage -l root如果之前root一直被锁定,你这次passwd root设了新密码后,账户会自动变成“有密码”状态,也就是解锁了。如果你平时根本不打算用root登录,只是为了让sudo正常工作(其实sudo正常工作跟root是否有密码完全无关),那可以在改完密码后再次锁定root:
passwd -l root这样操作之后,root的密码就变成一个无效的锁定标记,su -无法登录,但系统里所有需要root权限的服务、sudo流程都不受影响。我的习惯是:服务器上root必须锁定,只有sudo用户能干活;偶尔需要root shell就用sudo -i。桌面机上同理。这样即使账户密码泄露,攻击者也无法直接以root身份登录。
如果你恰恰相反——公司审计要求root可以直连登录,那记得同时改一下/etc/ssh/sshd_config里的PermitRootLogin选项,光改密码不改SSH配置的话,root照样连不上SSH,很多人会忽略这一点。改完配置要systemctl restart sshd才生效。
5.2 sudo用户密码忘了的替代解法
上面所有方案里,重置普通用户密码用的是passwd 用户名。但有一种特殊情况:这个普通用户在/etc/shadow里被设置了expiry时间,密码改完登录还是提示过期。这时在恢复shell或chroot环境里执行:
chage -d 0 用户名这条命令把“最后一次修改密码日期”设为0,强制用户下次登录时先改密码。注意如果普通用户密码是“强制过期”状态,passwd 用户名改完可能立不住,要配合chage一起用才稳。我帮人远程处理过好几回“改了密码还是登不进去”,十有八九就是卡在这个过期标志上。
顺便说一句,如果手头有root shell,想把某个普通用户提升为管理员,就是前面提过的:
usermod -aG sudo 用户名这个操作和改密码没关系,但既然进恢复模式了,一次把事情办完,省得下次再进。
5.3 密码过期策略与提醒配置
前面提到密码过期,这里展开一下。我见过不止一个运维同事因为密码过期被锁在门外,尤其是那种“半年才登一次”的备份服务器。
查看账户的过期信息:
chage -l 用户名把过期时间永久化:
chage -E -1 -M 99999 用户名其中-E -1表示账户永不过期,-M 99999表示密码最长使用天数接近无限。全局策略在/etc/login.defs里改,PASS_MAX_DAYS、PASS_MIN_DAYS、PASS_WARN_AGE三个参数分别对应最大天数、最小天数、提前警告天数。如果要设提醒,把PASS_WARN_AGE设成7,到期前一周用户登录就会看到警告。这个对root同样有效,设置后记得通过chage或实际登录验证一遍,别改完就以为万事大吉。
进阶一点的做法是给密钥登录的账户设置统一策略:比如所有用SSH key登录的账户,把密码过期设成99999,避免哪天策略扫描工具把一堆“长期未改密”的账户标红,然后又有人半夜打电话问你“root密码怎么又登不上”。这种问题,预防的成本远低于事后救火。
5.4 别把数据库root和系统root搞混
最后提醒一个非常常见的乌龙:很多同学在Ubuntu上装了MySQL或MariaDB,连数据库的时候提示类似ERROR 1045 (28000): Access denied for user 'root'@'localhost',第一反应是“我又忘了root密码”,然后跑到恢复模式里一通改,改完还是连不上——因为你改的是系统账户密码,数据库的root密码完全是另一个东西,存在MySQL自己的用户表里。
数据库root密码重置不需要动系统,方法是在MySQL配置文件里加skip-grant-tables跳过权限验证,重启服务后进入MySQL用ALTER USER重置密码,再把配置删掉重启。这个操作和系统root密码重置是两套流程,千万别混在一起。判断依据很简单:如果能正常登录系统、正常sudo,只是mysql -u root登录失败,那就是数据库问题,跟系统账户无关。
我在实际处理这类问题时,还有一个经验:如果是给客户或同事远程处理,动手前一定先确认对方说的“root密码”指哪个root。多问一句“你现在能不能正常登录系统”,能省掉后面所有弯路。