1. 问题背景与解决思路
上周帮同事处理一台跑在VirtualBox上的Ubuntu虚拟机时遇到了经典问题——密码遗忘。这种场景在开发环境、测试服务器上其实相当常见,特别是那些不常登录但又必须保留的虚拟机。不同于物理机需要准备U盘启动盘,虚拟机的密码重置其实有天然优势。
VirtualBox提供的虚拟化特性让我们能直接修改虚拟机配置参数,而Ubuntu基于GRUB引导的特性则给了我们单用户模式的入口。两者结合,就能在不破坏系统数据的情况下完成密码重置。下面分享的具体方法适用于Ubuntu 16.04到22.04的主流版本,其他Linux发行版原理类似但细节可能有差异。
2. 详细操作步骤
2.1 准备工作
首先确保VirtualBox已关闭目标虚拟机。建议先做个快照(菜单栏"控制"→"生成备份"),这个习惯很重要——我有次操作时误改了fstab文件导致系统无法启动,就是靠快照5秒回退的。
2.2 关键配置修改
- 右键虚拟机选择"设置"→"系统"→"主板",将"扩展特性"中的"启用EFI"取消勾选(重要!否则无法进入GRUB)
- 切换到"处理器"标签,勾选"启用PAE/NX"
- 在"显示"中显存调到128MB以上,避免后续操作界面显示异常
注意:如果原本就是传统BIOS模式(非EFI),则只需关注第三步。可以通过虚拟机日志文件查看启动方式。
2.3 进入单用户模式
- 启动虚拟机,在GRUB菜单出现时快速按下
Esc键(如果没看到菜单,启动时狂按Esc) - 选中带有"Ubuntu"字样的启动项(通常是第一个),按
e进入编辑模式 - 找到以
linux开头的行,在行末追加init=/bin/bash(注意前面要有空格) - 按
Ctrl+X启动,此时会进入root shell
这里有个细节:新版本Ubuntu可能默认隐藏GRUB菜单。若遇到这种情况,需要在虚拟机启动时按住Shift键而不是Esc。
2.4 密码重置实操
现在进入了最关键的挂载和修改环节:
bash复制# 重新挂载根目录为可读写
mount -o remount,rw /
# 查看用户列表(确认要修改的用户名)
ls /home/
# 修改密码(将username替换为实际用户名)
passwd username
# 按提示输入两次新密码
# 如果提示"Authentication token manipulation error",需要执行:
touch /.autorelabel
重要提示:如果系统使用了LUKS加密,需要先执行
cryptsetup luksOpen /dev/sdaX crypt(X是加密分区号),否则会提示找不到用户数据。
2.5 安全重启
完成密码修改后,执行以下命令确保安全重启:
bash复制# 同步磁盘数据
sync
# 有些系统需要重新标记SELinux上下文
fixfiles -F restore /
# 重启系统
exec /sbin/init
如果直接reboot可能导致文件系统损坏。我有次偷懒直接重启,结果导致ext4文件系统需要fsck修复,多花了半小时。
3. 特殊情况处理
3.1 GRUB加密的情况
有些安全要求高的环境会给GRUB设置密码,这时需要先解除加密:
- 在VirtualBox设置中挂载Ubuntu ISO镜像
- 从ISO启动选择"试用Ubuntu"
- 挂载原系统根分区:
bash复制sudo mkdir /mnt/root sudo mount /dev/sda1 /mnt/root - 编辑GRUB配置:
bash复制删除或注释sudo nano /mnt/root/etc/grub.d/40_customset superusers和password相关行 - 更新GRUB:
bash复制sudo chroot /mnt/root update-grub
3.2 LVM分区的处理
如果安装时选择了LVM分区,挂载步骤会更复杂些:
bash复制# 先激活卷组
vgchange -ay
# 查看逻辑卷路径
lvdisplay
# 挂载根分区(假设卷组名为ubuntu-vg)
mount /dev/ubuntu-vg/root /mnt
4. 预防措施建议
-
密码管理:建议使用
pwgen生成复杂密码后保存在Keepass等密码管理器bash复制sudo apt install pwgen pwgen -s 16 1 -
SSH密钥登录:对于开发用虚拟机,更推荐禁用密码登录,改用SSH密钥
bash复制# 本地生成密钥对 ssh-keygen -t ed25519 # 上传公钥到虚拟机 ssh-copy-id user@虚拟机IP -
定期快照:VirtualBox的快照功能可以保存多个时间点的状态,建议在重要配置变更前手动创建快照:
bash复制VBoxManage snapshot "VM名称" take "快照描述" --pause -
密码提示:可以在
/etc/motd中添加密码提示(避免明文):bash复制echo "提示:密码与2023年世界杯冠军有关" >> /etc/motd
5. 排错指南
问题1:修改密码后仍然无法登录
- 检查
/etc/shadow文件权限是否为640:bash复制chmod 640 /etc/shadow - 确认PAM配置:
bash复制
authselect check
问题2:系统启动卡在emergency mode
- 检查文件系统:
bash复制
fsck -y /dev/sda1 - 恢复默认SELinux上下文:
bash复制
restorecon -Rv /
问题3:GRUB菜单不出现
- 修改
/etc/default/grub:bash复制
GRUB_TIMEOUT=10 GRUB_HIDDEN_TIMEOUT= - 更新GRUB:
bash复制
update-grub
对于企业环境,建议将重要虚拟机的root密码纳入统一的密钥管理系统。我在某次应急响应中就遇到过因为管理员离职导致多台测试虚拟机被锁的情况,后来我们通过Ansible Vault实现了密码的集中管理:
yaml复制# ansible playbook示例
- hosts: virtual_machines
tasks:
- name: 修改root密码
user:
name: root
password: "{{ vaulted_root_password }}"
这个方法虽然看起来步骤不少,但实际操作起来10分钟内就能完成。比起重装系统后重新配置环境,绝对是值得掌握的基础技能。建议大家在测试环境多练习几次,关键时刻能省下大量时间。