做Linux运维这些年,重置密码是我处理过最高频的故障之一,没有"之一"也行。不管你是刚入行的新人,还是已经带团队的老手,迟早会遇到这么一出:某台服务器密码忘了、root密码过期、或者交接项目时上家没告诉你密码。更麻烦的是,很多机器跑着关键业务,没法随便重启,重启了还得掐着秒把密码改完。这篇文章我把Linux重置密码这件事从头到尾捋一遍,覆盖单用户模式、紧急模式、临时启动参数、chroot救援,还有普通用户的密码管理,每个方案都会把原理和操作串起来讲,你照着做就能解决问题。
先说清楚这篇文章适合谁。如果你手头有台能开机、能进引导菜单的Linux机器,但系统密码忘了或者失效,这篇文章就是给你看的。如果你面对的是云服务器,那思路会不太一样——云厂商的控制台一般自带重置密码功能,或者通过VNC方式进单用户模式,具体看厂商文档,不在这篇文章的范围内。物理机和自建虚拟机是重点,因为你能直接接触到开机引导过程。
1. 重置密码前先想清楚这几件事
很多人一拿到密码重置的需求,脑子里的第一反应是"进单用户模式改一下就行"。想法没错,但直接上手容易踩坑。我在动手之前,至少会确认三件事:这台机器是什么Linux发行版、根文件系统能不能挂载成读写模式、以及系统有没有开启SELinux或者AppArmor这类附加安全机制。这几个因素直接影响重置密码的具体路径。
密码重置之所以能实现,本质上是因为Linux的密码验证链路上有一个"后门":通过引导加载器(GRUB)去修改内核启动参数,让系统进入单用户模式或者直接切换到root shell。只要你人在机器旁边,或者能通过远程管理卡看到启动画面,就能拿到root权限去修改密码。这个"后门"不是漏洞,而是设计上就给运维人员留的管理通道,只是很多人没意识到它有多强大。
有一个细节必须提前知道:重置root密码和重置普通用户密码的难度不一样。普通用户密码忘了,用root身份执行一条passwd命令就完事;root密码忘了,才需要走引导级别的操作。所以这篇文章的重头戏在root密码重置,但普通用户的部分也会覆盖到。
另外,密码重置之后通常还要考虑一件事:这台机器上有没有跑着加密分区(LUKS)?如果有,你在改密码之前大概率会被要求输入解密密钥。物理机上的LUKS加密卷在开机时会要求输入密码来解锁根文件系统,如果这个密码也忘了,那就不是单用户模式能解决的问题了,得用备份的密钥文件或者LUKS自身的恢复流程,这是另一个话题。我在实际处理中遇到过两次这种叠加情况,每次都得先确认"你忘的到底是哪一个密码"。
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. 最常用的路子:通过GRUB进入单用户模式重置密码
单用户模式是Linux系统提供的一个特殊运行级别,它只加载最基本的服务,文件系统挂载后直接给你一个root shell,不需要登录。CentOS 6以前只需要在grub启动项里加一个s或者single参数,CentOS 7及以后的systemd时代,操作方法变了但原理还是一样的。
2.1 CentOS 7 / RHEL 7 系的具体操作
CentOS 7是现在存量很大的系统版本,我用它来演示第一套完整操作。先重启机器,在GRUB菜单出现的时候,按键盘上的e键进入编辑模式。如果你没看到GRUB菜单,可能是开机时菜单显示时间太短,可以在开机时快速按几次Esc或者Shift键呼出菜单。
进入编辑界面后,找到以linux16或者linux开头的那一行,这一行很长,包含了内核路径和各种启动参数。用方向键把光标移到这行末尾,在行尾添加一段内容:
code复制rd.break
编辑完成后按Ctrl+X或者F10启动系统。系统会进入一个特殊的emergency环境,root文件系统被挂载为只读,而且根目录被切换到了一个临时的initramfs文件系统上。这时候你看到的目录结构是有限的,实际的系统根目录挂在/sysroot下面。
接着按顺序执行这三条命令:
bash复制mount -o remount,rw /sysroot
chroot /sysroot
passwd root
第一条命令把真实的根文件系统重新挂载为可写,因为默认是只读状态,不先改权限的话后面改密码根本写不进去。第二条命令切换进真实系统的根目录,第三条命令执行密码修改。passwd会提示你输入两次新密码,输入时屏幕上不会显示任何字符,这是正常的,别以为键盘坏了。
改完密码后,还需要处理SELinux的问题。如果这台机器开启了SELinux,直接重启会因为安全上下文的变化导致登录异常。稳妥的做法是退出chroot环境后,在/sysroot下创建一个.autorelabel文件:
bash复制touch /.autorelabel
exit
exit
.autorelabel文件的作用是让系统在下次启动时自动重新标记文件的安全上下文,确保SELinux环境下root密码文件等内容的标签正确。创建完这个文件后,系统重启会自动执行relabel过程,完成后会自动删除这个文件。这一步是我踩过坑才补上的,早些年我改完密码直接重启,结果SELinux报错导致系统反复重启,后来才明白要加这个标记。
重启后就能用新密码登录root了。整个过程看起来就几步,但是每步为什么这么做,我建议你理解清楚:rd.break的本质是让内核在切换到真实根文件系统之前停下来,这时initramfs是临时的,真正的系统在/sysroot里,你需要在上面操作。
2.2 从CentOS 7到Rocky Linux、AlmaLinux都通用
Rocky Linux和AlmaLinux作为CentOS停更后的主流替代品,引导流程和CentOS 7基本一模一样。唯一可能存在的差异是GRUB菜单的默认等待时间,以及部分新版本默认使用linuxefi而不是linux16(UEFI引导时会出现)。操作方法不变:找到内核启动参数那一行,末尾加rd.break,后面步骤完全一致。
CentOS 8、Rocky 8、Rocky 9这些系统也是一样的思路。systemd时代的单用户模式入口其实有好几个,rd.break是其中之一,还有的方法我们后面会讲。
2.3 Ubuntu / Debian 系的处理方式
Ubuntu的引导流程和CentOS有区别,但整体思路相通。Ubuntu 18.04及以后版本用的是GRUB 2,开机时在GRUB菜单界面按e进入编辑模式,找到以linux开头的那一行(也可能叫linuxefi),在行尾添加:
code复制init=/bin/bash
这里要特别注意Ubuntu的一个坑:默认根文件系统是只读挂载的,你进入bash之后先要重新挂载根分区为读写,否则改密码时一样写不进去。所以完整的操作是:
bash复制mount -o remount,rw /
passwd root
在Ubuntu上执行完passwd之后,直接reboot -f强制重启就行,不需要像CentOS那样处理SELinux的问题,因为Ubuntu默认用的是AppArmor,虽然它也涉及安全上下文,但重置密码这个操作通常不会触发类似SELinux的阻档问题。
Ubuntu还有一条特殊的路径:在GRUB菜单中选择"Advanced options for Ubuntu",然后进入"recovery mode",在恢复菜单里选择root - Drop to root shell prompt,这样也能直接拿到root shell。这个路径的好处是不需要手改内核参数,对不熟悉命令行操作的人来说更直观。进入shell后再挂载根为可写、改密码即可。
2.4 国产系统(麒麟、统信UOS)的兼容情况
国产操作系统近些年普及度提升了不少,很多政企环境的服务器上跑的是麒麟(Kylin)或者统信UOS。它们的内核普遍是Linux 4.19或更新版本,引导器同样是GRUB 2,所以rd.break和init=/bin/bash这两种方法通常都能用。
我帮客户处理过一台麒麟V10服务器,操作路径和CentOS 7完全一样。唯一要注意的是部分麒麟系统默认开启了secure boot,这时GRUB菜单编辑可能受限,需要在BIOS里临时关闭secure boot,或者在GRUB里使用密码保护之外的入口。麒麟系统在改完密码后也建议检查一下SELinux状态(部分版本启用了SELinux),同样用touch /.autorelabel来避免上下文问题。
3. 另一种常用方案:修改内核参数直接进bash
除了rd.break,还有一种思路是让内核在启动后直接执行一个bash作为init进程,而不是走完整的systemd初始化流程。这种方法在CentOS 6时代特别常见,在systemd时代依然好用,而且步骤上更简洁。
3.1 用init=/bin/bash参数启动
还是老流程:重启机器,在GRUB菜单按e编辑启动项,找到内核参数所在行,在行尾添加:
code复制init=/bin/bash
然后按Ctrl+X启动。系统会跳过systemd,直接以bash作为第一个进程运行,你马上就能得到一个root shell。
但这一步有个关键点:用init=/bin/bash启动的系统和用rd.break进入的环境不一样,此时根文件系统已经正常挂载了,但依然是只读状态。所以下一步是先重新挂载:
bash复制mount -o remount,rw /
passwd root
这样就完成了密码修改。在这个环境里,网络服务、systemd的日志系统都不会启动,适合做密码修改这种简单的维护操作。改完之后执行exec /sbin/init可以重新启动完整的系统初始化流程,或者直接reboot -f强制重启。
3.2 两种方案的取舍和选择
很多新人会纠结到底用rd.break还是init=/bin/bash,我的建议是:CentOS 7及以上首选rd.break,因为它会正确挂载SELinux相关的文件系统,配合.autorelabel能够规避大部分安全问题;init=/bin/bash则更通用,几乎在所有发行版上都能生效,特别适合那些因为某些内核模块没加载导致rd.break环境不完整的场景。
有一类特殊情况我会优先选择init=/bin/bash:根文件系统是LVM逻辑卷,并且设备映射需要依赖initramfs中的工具时。rd.break发生在initramfs阶段,此时真实根还未挂载,而直接用init=/bin/bash时initramfs已经完成了根文件系统的切换,挂载层面更接近正常启动状态,可以少处理一层mount问题。
3.3 UEFI + Secure Boot的影响
现在新出厂的服务器基本都启用了Secure Boot。如果你在GRUB编辑界面改了内核启动参数,Secure Boot会校验内核和initramfs的数字签名,改动后的参数可能导致校验失败。不同主板的表现不一样,有些直接拒绝启动,有些会提示"Verification failed: (0x1A) Security Violation"。
解决思路有两个方向:一是在BIOS里临时关闭Secure Boot,改完密码后再打开;二是利用GRUB本身的签名机制——GRUB编辑时修改的不是内核文件,而是传给内核的参数,部分发行版对启动参数不做严格签名校验,实测不少系统能直接带参数启动。但哪些能过、哪些不能过并不好一概而论,稳妥起见,如果你不确定,进BIOS把Secure Boot关掉一次,重置完再恢复。
4. 如果系统连单用户模式都进不去:挂载硬盘的last resort方案
上面讲的都是系统能正常进入GRUB菜单的情况。但我也遇到过更惨的:服务器在机房,没有显示器,远程管理卡(IPMI/BMC)的密码也忘了,根本看不到启动画面。这时候物理介入不现实,只能靠带外管理——而带外管理的密码又属于另一个领域。前面热词里有人搜"超微主板IPMI密码重置",说白了就是同一个问题的硬件版本:操作系统密码和BMC密码是两条线,BMC密码忘了要看主板型号,有的支持跳线清空,有的只能通过IPMI工具在系统内重置。
但在系统层面,还有一条兜底的路:把系统盘拆下来,挂到另一台正常工作的Linux机器上,通过chroot的方式重置密码。这个方法虽然操作上要插拔硬盘,但原理和rd.break里的chroot是相通的,而且完全不依赖原系统的引导流程。
4.1 目标磁盘挂载与chroot环境准备
假设你现在有一台正常工作的Linux机器(救援机),原系统盘已经通过SATA/USB/硬盘盒接到了这台机器上。先查看分区结构:
bash复制lsblk
通常会看到类似sdb1(EFI分区)、sdb2(根分区)这样的结构。把根分区挂载到救援机的一个目录:
bash复制mount /dev/sdb2 /mnt
mount /dev/sdb1 /mnt/boot/efi
mount --bind /dev /mnt/dev
mount --bind /proc /mnt/proc
mount --bind /sys /mnt/sys
后三条mount --bind命令是为了让chroot环境里面能正常访问设备节点和内核接口。如果不做这三条绑定,chroot之后你执行的一些命令可能会报"cannot open /dev/null"之类的错误。
然后切换到目标系统环境:
bash复制chroot /mnt
passwd root
到了这一步就和之前的操作一样了,passwd root会直接修改目标系统上的密码。改完后退出chroot并清理挂载:
bash复制exit
umount /mnt/sys /mnt/proc /mnt/dev /mnt/boot/efi /mnt
把硬盘装回原机器,开机就能用新密码登录了。这套方法对虚拟机的虚拟磁盘同样适用,我常在VMware或者KVM宿主机上直接对虚拟磁盘文件做类似处理——先把磁盘映射出来,再挂载、chroot、改密码,原理一模一样。
4.2 Ubuntu/Debian和CentOS在chroot时的差异
在chroot环境里改密码,有一个需要注意的差异:不同发行版的passwd命令依赖的库文件都在根分区上,所以只要根分区挂载正确,passwd一般都能执行。但如果遇到"passwd: cannot open /etc/shadow"或者"Authentication token manipulation error"这类错误,大概率是根分区的读写权限没对,确认一下mount的时候是不是默认只读了(部分系统分区在异常挂载后会以只读方式挂载)。
另外提示一下,如果原系统开启了SELinux,通过chroot改完密码后,建议在/mnt下也创建.autorelabel:
bash复制touch /mnt/.autorelabel
这样原系统在下次启动时会重新标记安全上下文,避免密码文件或者shadow文件的SELinux标签不正确导致登录异常。
4.3 LVM卷和磁盘加密的额外处理
现在很多系统在安装时默认会用LVM做逻辑卷管理,比如根分区是/dev/mapper/centos-root或者/dev/mapper/ubuntu--vg-ubuntu--lv这样的路径。在救援机器上执行lsblk时,如果看不到实际的根分区而是看到LVM设备,需要用vgscan和lvscan先激活卷组:
bash复制vgchange -ay
这个命令会激活所有卷组,让逻辑卷设备出现在/dev/mapper/下面。之后再挂载逻辑卷:
bash复制mount /dev/mapper/centos-root /mnt
如果你还启用了LUKS全盘加密,那在挂载之前必须解锁加密分区:
bash复制cryptsetup luksOpen /dev/sdb2 cryptroot
执行后会提示输入加密分区的密码或密钥文件。这就回到了我开头说的那句话:你忘的到底是哪一个密码。如果真的连LUKS密码都忘了,那这条路也走不通了,只能找安装时备份的密钥文件,或者寄希望于你原来的密码记录里有加密分区的密码。
5. 普通用户密码的管理和"密码过期"问题
很多时候"密码重置"的需求并不一定发生在root身上。比如同事离职没交接账号、某台服务器上有个应用的专用账户密码找不到了,或者用户自己把密码改坏了导致登录不了。这类问题处理起来简单得多,只要你有root权限。
5.1 passwd命令的进阶用法
用root身份执行passwd 用户名就能重置指定用户的密码,比如:
bash复制passwd zhangsan
这个命令会交互式地要求输入两次新密码。如果你需要非交互式地设置密码,比如在脚本里批量操作,可以用:
bash复制echo "NewPassword123" | passwd --stdin zhangsan
注意--stdin这个参数是Red Hat系专属的,Debian/Ubuntu上的passwd不支持这个参数,需要用其他方法,比如通过chpasswd:
bash复制echo "zhangsan:NewPassword123" | chpasswd
chpasswd是更通用的方案,几乎所有Linux发行版都自带,非常适合批量修改多个用户的密码。我把这个记在常用命令清单里很多年了,遇到要批量重置密码的场景非常省事。
5.2 用户密码过期与锁定状态排查
有一种特殊假象:用户说"密码忘了",其实并不是密码错误,而是密码过期了。Linux的密码有效期由chage命令管理。查看某个用户的密码策略:
bash复制chage -l zhangsan
输出的信息里会包含"密码过期时间""密码失效时间"等字段。如果发现密码已经过期,你可以直接把过期时间调整为永不:
bash复制chage -E -1 -m 0 -M 99999 zhangsan
这样设置后密码就不会因为老化策略而强制失效。-M 99999表示密码最大使用期限是99999天,这基本等于永久;-m 0表示最小修改间隔为0天;-E -1表示账户永不过期。日常运维中,给服务账户创建完后,我习惯直接做这一轮设置,避免过几个月密码过期导致应用服务异常。
还有一个和"密码过期"非常容易混淆的问题是账户被锁定。passwd -S zhangsan可以看出账户当前的状态,如果显示LK表示被锁定(锁定的原因可能是多次密码错误触发了pam_faillock),需要先解锁:
bash复制passwd -u zhangsan
如果/etc/shadow里这个用户密码位是!开头,也是锁定状态。这种状态通常和密码遗忘无关,但用户端的表现都是"登录不了",排查时值得多看一眼。
5.3 通过sudo免密来管理密码
有些场景下你拿不到root密码,但手里有一个sudo权限的普通用户。这时可以用sudo权限来重置root或者其他用户的密码:
bash复制sudo passwd root
sudo passwd zhangsan
如果你所在的环境连sudo密码都忘了,但知道目标用户有sudo权限,而且/etc/sudoers里配了NOPASSWD,那么可以直接执行上面的命令而不需要输入sudo密码。如果sudoers里配置了需要密码,那就无解了,只能走前面讲的单用户模式或者带外管理。
6. 实操中踩过的坑和常见问题排查
这一部分是我最想分享的。密码重置看起来简单,但我在实战中见过太多"按教程操作却失败"的案例,问题往往出在一些不起眼的细节上。
6.1 问题速查表
我把常见问题整理成了一张表,方便你在遇到异常时快速定位:
| 现象 | 可能原因 | 解决方法 |
|---|---|---|
| 进GRUB编辑后改了参数但启动后没进单用户模式 | 修改的内核参数行不对,或者没按Ctrl+X启动 | 确认编辑的是linux/linux16/linuxefi开头的那一行,不是vmlinuz开头的GRUB行 |
修改密码时报passwd: Authentication token manipulation error |
根文件系统是只读挂载 | 先执行mount -o remount,rw /或者对/sysroot执行同样的操作 |
| 改完密码重启后root登录不上 | SELinux上下文问题 | 在rd.break环境里创建/.autorelabel,让系统启动时重新标记上下文 |
| 输入新密码时不显示字符 | 正常现象,passwd出于安全考虑不回显 |
正常输入并回车即可,不要以为键盘坏了 |
| 重启后grub参数丢失,系统正常启动 | 正常现象,GRUB编辑是临时生效的 | 如果希望永久修改启动参数,需要改/etc/default/grub里的GRUB_CMDLINE_LINUX |
密码重置完用户依然无法登录,查看secure log发现Authentication failed |
密码哈希算法不兼容 | 确认系统使用的密码哈希算法(authconfig或/etc/login.defs中的ENCRYPT_METHOD),重新生成兼容的哈希 |
chroot环境里passwd执行报cannot open /etc/shadow |
根分区挂载有问题或SELinux隔离 | 检查挂载命令是否完整,确保目标分区的权限正常,必要时加-o rw重新挂载 |
6.2 改完密码后键盘布局导致的密码错误
这是一个非常隐蔽的坑。服务器通常在机房,没有本地键盘;你用IPMI或KVM远程连接进去,这时控制台使用的键盘布局可能和系统设置不一致。比如系统设置的是us布局,而你的远程客户端是德语或法语键盘,按某个键输出的字符和你预期的不一样,设置密码时输进去了错误的字符,等于把自己锁在门外。
这种问题最好的规避方式是在设置密码时尽量使用纯ASCII字符,避免使用那些在不同键盘布局下映射不同的特殊字符,比如@、#、$、[、\这些。如果你怀疑已经因为键盘布局把密码设置错了,最稳妥的办法是再走一遍单用户模式重置,重置时输入密码后反复确认两遍,然后先不急着重启,用passwd -S root看一下状态确认没有报错,或者干脆在重置后直接登录一次测试。
6.3 密码过期提醒与免费图形界面工具
热搜词里有"linux密码过期提醒通知",这确实是一个运维场景。系统默认情况下,用户在密码快过期时登录,终端会提示"Warning: your password will expire in N days"。如果用户使用SSH密钥登录,他根本不会看到这个提示,等到密码真正过期了才发现连不上了。
如果你希望主动监控并提醒密码即将到期的账户,可以写一个简单的巡检脚本,定时扫描/etc/shadow里所有用户的密码过期时间。核心逻辑是读取shadow文件第三列(最后一次修改时间)和第五列(最大有效期),结合当前日期计算出剩余的过期天数:
bash复制awk -F: '$2!="!" && $2!="*" && $5>0 {print $1, $3, $5}' /etc/shadow
再结合chage -l命令去获取精确信息。写一个crontab任务,每天检查一次,到期前7天发一封邮件或者在企业微信、钉钉群里推送提醒。这个思路比让用户自己盯着登录提示要可靠得多,我亲自给团队做过一版,上线后"密码过期导致服务异常"的工单数量明显下降了。
6.4 关于"400密码重置助手"之类的工具
系统维护中还会遇到厂商自带的密码重置工具,比如硬件管理软件的控制台工具,搜"400密码重置助手"出来的通常是特定设备厂商的带外管理系统。这些工具不在Linux通用技术的讨论范围内,它们的原理往往也是基于带外管理通道去修改系统密码。如果你要处理的是物理服务器的操作系统密码,优先考虑本文讲的通用方法,不要依赖特定厂商的私有工具,因为换了一台设备可能就不适用了。
7. 密码重置后的必备收尾操作
改完密码只是第一步,真正专业的做法是改完密码后做一轮系统检查,避免因为这次操作引出其他问题。
首先要检查SSH配置。如果系统禁用了root通过SSH登录(/etc/ssh/sshd_config里PermitRootLogin no),即使你成功重置了root密码,远程SSH登录依然会被拒绝,只能在控制台或者通过普通用户su切换来登录。如果你需要远程直接用root登录,需要修改这个配置项并重启sshd服务:
bash复制sed -i 's/^#PermitRootLogin.*/PermitRootLogin yes/' /etc/ssh/sshd_config
systemctl restart sshd
注意这是一把双刃剑,开启root远程SSH登录会降低服务器的安全性,建议只在临时需要时开启,用完再关回去。
其次要确认SELinux或者AppArmor的状态没有异常。CentOS/RHEL系列检查:
bash复制getenforce
如果输出是Enforcing,并且有过.autorelabel流程,重启后系统会重新标记文件上下文,这个过程可能会让启动时间变长,标记完成后会自动恢复正常。
还有就是要系统性地记录密码变更信息。我通常会在改完密码后把变更记录写到运维文档或者内部的密码管理系统中,包括变更时间、修改了哪个用户、是哪个人的账号、原因是什么。密码管理这件事,团队协作时最怕的就是"改了不告诉别人",导致后续所有人对接时都以为老密码还有效,反复尝试后账户被锁定,问题越搞越复杂。
最后,如果你的机器是企业内部服务器,重置密码后建议顺手检查一下这台机器上有没有配置了基于密钥的自动化任务,比如定时备份、ansible推送、cron脚本等。这些任务通常会用到某个用户的凭据,如果改了密码,可能导致这些自动化任务失败。我经历过一次改了某台数据库服务器的密码,结果第二天凌晨的备份任务全挂了,因为备份脚本里用的服务账户密码还是旧的。所以在改密码前,先扫一眼这台机器上关联的服务和定时任务,改完后在下一个执行周期观察是否正常。
密码重置这事,说简单也简单,就几条命令的事;说复杂也复杂,因为一旦做错,可能把一台机器搞到无法登录。我个人在实际操作中的体会是,尽量用标准流程,不要贪图省事跳步骤,尤其是mount -o remount,rw和.autorelabel这两个细节,不知道有多少人在这上面翻了车。最后再分享一个小技巧:如果你的环境里有虚拟机模板或者容器镜像,建议预先留一份系统快照,密码真忘了的时候,直接从快照恢复可能比重置密码更省事,前提是你接受恢复期间的少量数据丢失。这算是长期运维中一个性价比很高的备选方案。
