Arch Linux KVM 镜像离线初始化指南
适用范围:本文用于离线修改一份未运行的 Arch Linux KVM 镜像。先备份镜像,并根据实际镜像格式、分区和文件系统替换示例值。
重要限制:
virt-customize和qemu-nbd是两种不同的修改方式。使用virt-customize时不要同时挂载同一镜像;使用qemu-nbd挂载后,应直接编辑挂载目录,不要再对该镜像执行virt-customize。
方案 B:使用 qemu-nbd 挂载镜像
使用 qemu-nbd 连接镜像
加载模块:
sudo modprobe nbd max_part=8
连接:
sudo qemu-nbd \
--connect=/dev/nbd0 \
/var/lib/libvirt/images/arch
查看磁盘分区
lsblk /dev/nbd0
示例:
NAME SIZE TYPE
nbd0 2G disk
├─nbd0p1 1M part
├─nbd0p2 300M part
└─nbd0p3 1.7G part
确认根分区
查看:
blkid /dev/nbd0p*
通常:
| 分区 | 用途 |
|---|---|
| nbd0p1 | GPT 保留 |
| nbd0p2 | EFI |
| nbd0p3 | Linux 根分区 |
挂载:
sudo mount /dev/nbd0p3 /mnt
如果有 EFI:
sudo mkdir -p /mnt/boot
sudo mount /dev/nbd0p2 /mnt/boot
方案 A:使用 virt-customize 设置 root 密码
推荐使用 virt-customize,但执行时镜像必须未被挂载、未被虚拟机使用。不要把真实密码写入命令历史或文章。
原文命令(保留,仅供对照;不要在实际系统中使用固定弱密码):
sudo virt-customize \
-a /var/lib/libvirt/images/arch \
--root-password password:12
补充:实际执行时,将 IMAGE_FILE 替换为实际镜像文件名,并使用受保护的密码文件:
sudo virt-customize \
-a /var/lib/libvirt/images/IMAGE_FILE \
--root-password file:/path/to/protected-password-file
密码文件应只允许当前管理员读取,并在操作完成后删除。不要使用示例中的固定弱密码。
方案 A:使用 virt-customize 配置 systemd-networkd DHCP
创建 networkd 配置文件
如果前面已经使用 qemu-nbd 挂载镜像,请先卸载并断开镜像,再执行下面的 virt-customize 命令;不要让两种修改方式同时操作同一镜像。
文件路径:
/etc/systemd/network/20-wired.network
内容:
[Match]
Type=ether
[Network]
DHCP=yes
不绑定网卡名称,自动匹配所有以太网设备,适合 KVM/libvirt 虚拟机。
写入镜像
创建临时文件:
cat >/tmp/20-wired.network <<EOF
[Match]
Type=ether
[Network]
DHCP=yes
EOF
写入:
sudo virt-customize \
-a /var/lib/libvirt/images/arch \
--write \
/tmp/20-wired.network:/etc/systemd/network/20-wired.network
启用 systemd-networkd
sudo virt-customize \
-a /var/lib/libvirt/images/arch \
--run-command \
'systemctl enable systemd-networkd'
启用 DNS:
sudo virt-customize \
-a /var/lib/libvirt/images/arch \
--run-command \
'systemctl enable systemd-resolved'
修复 resolv.conf
sudo virt-customize \
-a /var/lib/libvirt/images/arch \
--run-command \
'rm -f /etc/resolv.conf' \
--run-command \
'ln -s /run/systemd/resolve/stub-resolv.conf /etc/resolv.conf'
方案 B:进入挂载的系统环境
sudo arch-chroot /mnt
修复 pacman keyring
遇到的问题
安装软件:
pacman -S fish
出现:
warning: Public keyring not found; have you run 'pacman-key --init'?
error: keyring is not writable
error: required key missing from keyring
原因
- 镜像未初始化 pacman keyring
- keyring 文件损坏
- 镜像过旧
修复
初始化:
pacman-key --init
导入官方密钥:
pacman-key --populate archlinux
更新 keyring(保留原文命令):
pacman -Sy archlinux-keyring
补充:正常升级时使用完整升级命令:
pacman -Syu archlinux-keyring
不要长期执行部分升级。若旧镜像的密钥环已经无法验证仓库,先在隔离环境中确认当前 Arch 的密钥环恢复流程,再继续升级。
升级系统并安装软件
更新系统:
pacman -Syu
安装软件,例如 fish:
pacman -S fish
locale 警告处理
进入 chroot 时可能出现:
bash: warning: setlocale: LC_ALL: cannot change locale (zh_CN.UTF-8)
原因:locale 未生成。
修复:编辑 /etc/locale.gen,取消注释:
#zh_CN.UTF-8 UTF-8
改为:
zh_CN.UTF-8 UTF-8
生成 locale:
locale-gen
卸载镜像
退出 chroot:
exit
卸载文件系统:
sudo umount -R /mnt
如果卸载失败,先用 mount、lsof 或 fuser 找出仍在使用 /mnt 的进程并停止它。除非确认不会再访问镜像,否则不要直接使用懒卸载:
sudo umount -l /mnt
断开 nbd:
sudo qemu-nbd \
--disconnect \
/dev/nbd0
卸载 nbd 模块(可选):
sudo modprobe -r nbd
检查确认 nbd0 已消失:
lsblk
遇到的问题总结
| 问题 | 原因 | 解决 |
|---|---|---|
| guestmount 下 pacman 下载失败 | FUSE 写入异常 | 改用 qemu-nbd |
| mount /dev/nbd0pX 失败 | X 是占位符 | 使用真实分区 |
| pacman keyring 不可写 | keyring 未初始化 | pacman-key –init |
| locale 警告 | locale 未生成 | locale-gen |
| 虚拟机无网络 | 没有 networkd 配置 | systemd-networkd DHCP |
| root 无密码 | 镜像未初始化 | virt-customize 设置密码 |
推荐初始化顺序
方案 A:使用 virt-customize
- 备份镜像,并确认虚拟机没有使用该镜像。
- 在镜像未挂载的状态下,用
virt-customize设置密码和写入网络配置。 - 退出
virt-customize后,才可以选择使用qemu-nbd挂载镜像进行检查,或直接启动虚拟机验证。
方案 B:使用 qemu-nbd 和 arch-chroot
- 备份镜像。
- 使用
qemu-nbd连接并确认实际分区。 - 挂载根分区和 EFI 分区,直接编辑配置文件。
- 进入
arch-chroot,初始化pacman-key并执行完整系统升级。 - 安装所需软件,退出 chroot,卸载所有分区后断开 NBD。
原文推荐顺序(保留):
qemu-nbd挂载镜像virt-customize:设置 root 密码、写入 systemd-networkd 配置、enable networkd/resolvedarch-chrootpacman-key初始化pacman -Syu- 安装软件
- 卸载镜像
上述顺序属于原文记录。由于
qemu-nbd和virt-customize不能同时操作已挂载镜像,实际执行时必须选择上面的方案 A 或方案 B,不能照此顺序混用。
两种方案不要同时操作同一份已挂载镜像。该流程适合制作 KVM/libvirt Arch Linux 基础镜像。