阿里云轻量应用服务器 Ubuntu 迁移 Arch Linux 操作手册
阿里云轻量应用服务器 Ubuntu 迁移 Arch Linux 操作手册
这篇记录一次在阿里云轻量应用服务器上,把正在运行的 Ubuntu 换成 Arch Linux 的过程。适用这台 x86_64、单盘、GPT、UEFI、ext4、DHCP 的机器,整理日期是 2026-10-17。
高风险:这是替换操作系统,不是普通升级。 会中断服务,并可能导致 SSH 失联或无法启动。先完成异地备份,并确认控制台还能连上、能看到启动画面,再进入会改磁盘的步骤。不要把全文复制后一次执行。
1. 记录范围与成功结论
本次采用的路线是:1
2
3
4
5
6
7
8Ubuntu 正常运行
→ 在 /opt/arch-install/root.x86_64 准备 Arch 基础系统
→ 下载 ISO 到 /boot/iso/archlinux.iso
→ 用现有 Ubuntu GRUB loopback 启动 Arch Live,copytoram=y
→ 在 Live 中替换 /dev/vda3 的根目录内容,保留 ext4 和 UUID
→ 挂载 EFI,arch-chroot 到硬盘 Arch
→ 配置 initramfs、GRUB、DHCP 和 admin SSH 密码登录
→ 退出、卸载、重启,从硬盘启动 Arch Linux
迁移结束后,系统可以从硬盘启动并登录。现场记录没有逐条留下全部命令输出,部分截图也只有失效链接,因此不能把后面每一条建议都说成已经在这台机器上执行并验证过。
正文按三种材料区分:
- 现场参数:设备、UUID、路径、地址和配置,都来自这台机器当时的记录。
- 整理后的操作:把步骤重排,把被压成一行的配置拆开,并修正其中的错误和风险。
- 安全修订方案:根目录替换改为“先隔离旧文件,再复制且不删除源目录”,用来代替嵌套源目录上的
rsync --delete。这个修订方案没有在这台机器上再执行一遍。
本文不是通用无人值守重装脚本。其他机器必须重新确认磁盘、UUID、引导方式、网卡及恢复条件。
2. 本次真实环境与参数
| 项目 | 原记录值 | 说明 |
|---|---|---|
| 平台 | 阿里云轻量应用服务器 | 沿用原实例 |
| 原系统 | Ubuntu | 有 Docker 等应用数据 |
| 原主机名 | iZwz99y3lhlxdjrkl7geclZ | 来自终端提示符 |
| 架构 | x86_64 | 使用 x86_64 Bootstrap / ISO |
| 内存 | 3.5 GiB | Ubuntu 检查时 available 约 2.7 GiB |
| Swap | 0 B | 内存不足时不能依赖交换空间 |
| 系统盘 | /dev/vda,50 GiB | Virtio 磁盘 |
| 分区表 | GPT | 对话后续检查总结确认 |
/dev/vda1 | 1 MiB | 原对话称 BIOS Boot;本次 UEFI 不使用它,保留 |
/dev/vda2 | 200 MiB,FAT32 | EFI System Partition,挂载 /boot/efi |
| EFI UUID | 4AA9-6FC3 | 必须现场复核 |
/dev/vda3 | 49.8 GiB,ext4 | Ubuntu 根分区,随后作为 Arch 根分区 |
| 根 UUID | b4cbd348-1941-41f0-908b-42f34f456dcc | 保留文件系统时保持不变 |
| 原可用空间 | 约 24.2 GiB,使用率 46% | 后续下载、复制会改变此值 |
| 启动方式 | UEFI | /sys/firmware/efi 存在 |
| Secure Boot 检查 | This system doesn't support Secure Boot | 不等于所有云实例都支持相同配置 |
| 原 EFI 启动项 | Boot0006* Ubuntu | 路径 \EFI\ubuntu\shimx64.efi |
| 原 BootOrder | 0006,0000,0001,0002,0003,0004,0005 | 历史状态,不能当作新系统启动顺序 |
| 网卡 | eth0 | 新系统用 net.ifnames=0 配合配置 |
| IPv4 租约 | 172.17.31.160/18 | 私网地址,不写死为静态地址 |
| 网关 | 172.17.63.253 | 来自 DHCP 租约 |
| 网络方案 | systemd-networkd + DHCP | DNS 使用 systemd-resolved |
| 串口 | ttyS0,115200n8 | 保留启动日志输出 |
| Bootstrap 原文件 | ~/archlinux-bootstrap-x86_64.tar.zst | 这里的 ~ 是下载用户的家目录 |
| 安装源 | /opt/arch-install/root.x86_64 | 与目标根目录在同一分区 |
| ISO 版本 | 2026.10.01 | 本次历史版本,不代表以后最新版本 |
| ISO 本地路径 | /boot/iso/archlinux.iso | 位于 /dev/vda3 |
| Live 挂载目标 | /mnt/target | 必须实际挂载,空目录不算 |
| Arch 引导名称 | ArchLinux | EFI 路径通常 \EFI\ArchLinux\grubx64.efi |
| 最终 SSH 用户 | admin | 使用密码登录,禁止 root SSH 登录 |
| 新主机名配置 | archlinux | 原对话给出的设置 |
**未提供的参数:**公网 IP、最终 ArchLinux EFI 启动编号、最终内核版本及最终完整验收输出。本文不补造这些值。原对话的 0007 只是 EFI 编号示例。
3. 必须区分的四种执行环境
| 标签 | 当前环境 | / 的含义 | 可以做什么 |
|---|---|---|---|
| U | Ubuntu 宿主 | 正在运行的 /dev/vda3 | 下载、检查、准备 Bootstrap、配置旧 GRUB |
| B | Ubuntu 内的 Bootstrap chroot | 安装源目录 | 安装 Arch 软件及配置未来系统;仍用 Ubuntu 内核 |
| L | Arch Live ISO | 通常 airootfs / overlay | 离线挂载磁盘、替换根文件、进入目标 chroot |
| T | Live 中的目标 chroot | /mnt/target 对应的硬盘根 | 配置将来从硬盘启动的 Arch;仍使用 Live 内核 |
| A | 重启后的硬盘 Arch | /dev/vda3 | 验证真实启动、网络和 SSH 服务 |
判断时组合使用:1
2
3cat /etc/os-release
findmnt /
uname -r
cat /etc/os-release 在 B、L、T、A 都可能显示 Arch,单独使用不能证明已从硬盘启动。uname -r 在 chroot 中仍显示宿主内核。提示符也可能沿用宿主设置,不能作为充分证据。
在 L 中进入 T 前,额外检查:1
2
3mountpoint /mnt/target
findmnt -M /mnt/target
cat /mnt/target/etc/os-release
必须确认它是 /dev/vda3,且文件内容已经是 Arch。chroot 不是独立 Live 环境,不能用于安全覆盖仍在运行的 Ubuntu 根文件系统。
4. 风险边界与恢复准备
开始前完成:
- 在控制台创建可用的系统盘备份/快照,并核实当前产品的恢复方式;另做异地数据备份。
- 单独导出 Docker Compose、环境文件、数据库一致性备份、卷数据、网站配置、证书、SSH 公钥和应用配置。磁盘快照不自动保证数据库一致性。
- 验证阿里云远程控制台能实际连接、看到启动画面并输入命令。控制台是输入输出入口,不自动提供独立救援系统。
- 确认 TCP 22 入站规则允许管理员访问,并记录公网连接地址。
- 保存分区、UUID、路由、EFI 配置到本地电脑;服务器内的唯一副本不算异地备份。
- 规划停机窗口,停止业务写入后再制作最终数据备份。
禁止操作:
- 不对
/dev/vda3执行mkfs、wipefs或 DD;安装源和 ISO 都在该分区内。 - 不对
/dev/vda2重新格式化;本次复用现有 EFI。 - 不在运行中的 Ubuntu 对
/执行删除或镜像覆盖。 - 不因
copytoram=y或根目录为airootfs就认定 ISO 已完全脱离系统盘。 - 不用
umount -l、强制卸载或批量losetup -D绕过占用问题。 - 不将示例 EFI 编号、公网地址或旧 DHCP 租约直接当成新机器参数。
恢复边界:在替换前,旧 Ubuntu 仍可能作为回退入口;替换后,保留 Ubuntu EFI 文件不等于 Ubuntu 仍能启动。必须通过 Live、外部救援或备份恢复。
5. 环境检查(U)
1 | uname -m |
原 Ubuntu 内核中 CONFIG_BLK_DEV_INITRD、CONFIG_BLK_DEV_LOOP、CONFIG_VIRTIO_BLK、CONFIG_VIRTIO_NET 均为 y。这证明 Ubuntu 内核能力,不能替代新 Arch 内核/initramfs 验证。
原 GRUB 设置为 GRUB_DEFAULT=0、隐藏菜单、超时 1 秒;后面改为显示菜单,方便控制台选择。
6. Bootstrap 解压与基础安装(U → B)
6.1 下载与校验
本次文件已经下载到普通用户的 ~。下载入口使用 Arch 官方下载页。压缩包与签名必须来自同一个版本。
在解压前验证签名:1
gpg --verify archlinux-bootstrap-x86_64.tar.zst.sig archlinux-bootstrap-x86_64.tar.zst
若缺少签名公钥,从官方发布信息核对签名者及完整指纹后再导入。不能仅因“Good signature”就忽略公钥来源。原记录没有完整保留本次签名验证输出。
6.2 安装 Ubuntu 工具并解压
1 | sudo apt update |
不要先 sudo -i 再照抄 ~/...,否则 ~ 会变成 root 家目录。原记录曾安装 kexec-tools,但最终采用 GRUB ISO 路线,本文不要求使用 kexec。
6.3 进入 Bootstrap
以下手工挂载方式沿用原记录。各挂载只执行一次;重复操作前先检查 findmnt -R "$ARCHROOT"。1
2
3
4
5
6
7
8
9
10
11
12
13sudo -i
ARCHROOT=/opt/arch-install/root.x86_64
cp -L /etc/resolv.conf "$ARCHROOT/etc/resolv.conf"
mount --bind "$ARCHROOT" "$ARCHROOT"
mount -t proc proc "$ARCHROOT/proc"
mount --rbind /sys "$ARCHROOT/sys"
mount --make-rslave "$ARCHROOT/sys"
mount --rbind /dev "$ARCHROOT/dev"
mount --make-rslave "$ARCHROOT/dev"
mount --rbind /run "$ARCHROOT/run"
mount --make-rslave "$ARCHROOT/run"
chroot "$ARCHROOT" /bin/bash
cat /etc/os-release
现在进入 B。不要在这里运行会重启宿主或切换宿主网络的操作。
6.4 配置镜像与安装软件(B)
1 | cat > /etc/pacman.d/mirrorlist <<'EOF' |
镜像配置每个 Server 独占一行,单引号 heredoc 保留 $repo、$arch 给 pacman 展开。
原对话曾使用 pacman -Sy --needed archlinux-keyring 随后 pacman -Syu。本文优先完整升级;若旧密钥环确实阻止升级,应按官方密钥环恢复流程处理,不能长期停在仅同步数据库的状态,也不要关闭签名检查。
6.5 系统基础配置(B)
1 | ln -sf /usr/share/zoneinfo/Asia/Shanghai /etc/localtime |
原对话还建议 hwclock --systohc。chroot 共享宿主硬件接口,该命令可能修改宿主 RTC;本路线不需要在 Bootstrap 内执行,正式启动后按云环境时间同步方案处理。
配置 networkd 和 admin SSH 见第 11、12 节,可先在 B 中准备;迁移后的 T 中必须再次核对。安装源内只配置,不提前安装硬盘 EFI 引导。
6.6 退出并清理准备挂载(U)
1 | exit |
必须在 Ubuntu 宿主执行,且前面的自绑定挂载确实存在。若 busy,先关闭所有 Bootstrap shell、离开目录并排查进程,不能强制卸载。
检查安装源大小与内核:1
2
3
4du -sh /opt/arch-install/root.x86_64
ls -lh /opt/arch-install/root.x86_64/boot/vmlinuz-linux
ls -lh /opt/arch-install/root.x86_64/boot/initramfs-linux.img
df -h /
本文修订流程会临时保留旧 Ubuntu 文件并再复制一份 Arch;必须有足够剩余磁盘空间。3.5 GiB 内存不适合假定能额外装下完整 Arch 安装源,因此不把整套安装源搬到 tmpfs。
7. 下载阿里云 ISO 并检查(U)
本次用户指定且随后反馈已下载的 URL:1
2
3
4
5sudo mkdir -p /boot/iso
sudo wget -c \
https://mirrors.aliyun.com/archlinux/iso/2026.10.01/archlinux-2026.10.01-x86_64.iso \
-O /boot/iso/archlinux.iso
ls -lh /boot/iso/archlinux.iso
原对话还提供了以下候选地址,不表示现在一定可下载:
https://geo.mirror.pkgbuild.com/iso/2026.10.01/archlinux-2026.10.01-x86_64.isohttp://mirrors.cloud.aliyuncs.com/archlinux/iso/2026.10.01/archlinux-2026.10.01-x86_64.iso
公网镜像策略和内网可达性会变化;轻量应用服务器不保证可访问 ECS 内网镜像。HTTP 下载尤其需要可信签名验证。切换源时只对确定是同一文件的下载使用断点续传;校验失败应重新下载。
原记录中的 SHA256 为:1
684ded26c63240ff4a41e8c25ee84ea6da233f557364821f13d12c2b0a9059a5
该值是历史对话提供值,本文未独立验证其对应的 ISO,不能作为唯一信任依据。 应从可信官方发布渠道取得该版本的校验文件/签名,核对版本、文件名、完整散列及签名者。对本地重命名文件执行 sha256sum /boot/iso/archlinux.iso,与已验证的原始文件条目比较;不能不改路径就直接拿原名校验本地重命名文件。
检查 ISO 内部布局:1
2
3
4
5sudo mkdir -p /mnt/archiso
sudo mount -o loop,ro /boot/iso/archlinux.iso /mnt/archiso
ls -lh /mnt/archiso/arch/boot/x86_64/
sudo cat /mnt/archiso/boot/grub/loopback.cfg
sudo umount /mnt/archiso
必须核对内核、initramfs 的实际路径,后文仅适用原记录中的路径。copytoram=y 会占用大量内存;检查内存预算并停止不必要的业务。ISO 文件大小不等于最终全部内存占用。
8. Ubuntu GRUB loopback 引导 Live(U)
备份:1
2
3sudo cp -a /etc/default/grub /etc/default/grub.before-arch
sudo cp -a /etc/grub.d/40_custom /etc/grub.d/40_custom.before-arch
sudo cp -a /boot/grub/grub.cfg /boot/grub/grub.cfg.before-arch
编辑 /etc/grub.d/40_custom,保留原脚本头部,在末尾加入以下菜单。以 ISO 自带配置为最终依据,若路径或参数不同则先修正:1
2
3
4
5
6
7
8
9
10menuentry "Arch Linux Live ISO" --id arch-live {
insmod part_gpt
insmod ext2
insmod loopback
search --no-floppy --fs-uuid --set=root b4cbd348-1941-41f0-908b-42f34f456dcc
set isofile="/boot/iso/archlinux.iso"
loopback loop $isofile
linux (loop)/arch/boot/x86_64/vmlinuz-linux img_dev=/dev/disk/by-uuid/b4cbd348-1941-41f0-908b-42f34f456dcc img_loop=$isofile earlymodules=loop copytoram=y console=tty0 console=ttyS0,115200n8
initrd (loop)/arch/boot/x86_64/initramfs-linux.img
}
在 /etc/default/grub 修改已有定义,不叠加重复定义:1
2
3GRUB_DEFAULT=0
GRUB_TIMEOUT_STYLE=menu
GRUB_TIMEOUT=10
确认菜单第 0 项仍是 Ubuntu;0 只表示第一个菜单项,不固有代表 Ubuntu。1
2
3
4
5sudo update-grub
sudo grub-script-check /boot/grub/grub.cfg
sudo grep -A 15 'Arch Linux Live ISO' /boot/grub/grub.cfg
sudo grub-reboot arch-live
sudo grub-editenv list
应看到 next_entry=arch-live。这是旧 GRUB 的一次性菜单选择,与 UEFI 的 BootNext 是两个层级。语法检查不证明 ISO 一定可启动;一次性引导也不保证失败后自动回到 Ubuntu。
确认备份、控制台均可用,再执行:1
sudo reboot
Live 不继承 Ubuntu 的 admin 密码,首次从控制台进入。不要因 SSH 暂时不通就判断启动失败。
9. Live 验证与 ISO 源分区占用(L)
1 | cat /etc/os-release |
原对话确认 Live 根为 airootfs。但还必须检查完整依赖链:1
2/dev/vda3 → 挂载的源文件系统 → archlinux.iso → ISO loop
→ airootfs.sfs → squashfs loop → Live 根
也可能看到 squashfs 后端已转到 /run/archiso/copytoram/...,表示数据在内存路径。存在 loop 本身不是错误;关键是 loop 后端是否仍位于 /dev/vda3。 对可疑后端路径用 findmnt -T 实际后端路径 追溯文件系统,不能只搜索 /mnt/target 字样;同一分区可能挂在 /run/archiso/img_dev。
9.1 允许继续的条件
- Live 根不是
/dev/vda3。 - 活跃 Live squashfs/overlay 的后端不依赖该分区中的 ISO 或其他文件。
/dev/vda3没有被 archiso 以只读形式继续占用,或已经通过正常卸载完成释放。- 所有可能需要的工具已经可用,网络/控制台可工作,内存有余量。
若仍有 ISO 依赖:停在本节,不 remount 强行写入、不删 ISO、不 detach 正在用的 loop。 核对 /proc/cmdline 和该 ISO 的 copytoram 实现,必要时重新从正确参数启动或使用独立救援介质。仅当确认某个挂载/loop 已不被 Live 根依赖时,才按“最内层挂载 → 对应 loop → 外层源挂载”逐个正常释放并复查。不能把固定 loop0、loop1 写进批量卸载命令。
ISO 释放后尚未挂载目标时,findmnt -S /dev/vda3 应没有相关挂载。先按只读方式检查安装源:1
2
3
4
5
6mkdir -p /mnt/target
mount -o ro /dev/vda3 /mnt/target
findmnt -M /mnt/target
cat /mnt/target/opt/arch-install/root.x86_64/etc/os-release
ls -lh /mnt/target/opt/arch-install/root.x86_64/boot/
du -sh /mnt/target/opt/arch-install/root.x86_64
安装源必须为 Arch 且有内核。注意 ext4 普通只读挂载仍可能回放日志;若用于事故取证应采用专门的无写入流程,本文是安装流程。
9.2 Live 网络临时恢复
Live 网卡名可能不是 eth0,因为上述 Live 菜单没有设置 net.ifnames=0。先用 ip -br link 识别实际名字,再为实际网卡配置 DHCP、启动 networkd;不要直接照搬网卡名。临时修改 Live 的配置不会自动进入硬盘 Arch。
10. 根文件系统替换:安全修订方案(L)
10.1 为什么不直接照抄原来的 rsync –delete
原记录设置:1
2SRC=/mnt/target/opt/arch-install/root.x86_64
DST=/mnt/target
源目录位于目标内部。对目标使用 --delete,若安装源保护失效,rsync 会把源当成目标多余内容删除,后续出现文件消失或迁移中断。ISO 也有同样风险。
原记录用 --exclude='/opt/arch-install/***' 等保护目录;标准 rsync 排除规则通常同时影响发送端与接收端删除保护,但保护依赖路径和选项,不是任意情形的保证。不能添加 --delete-excluded,也不能只写发送端隐藏规则就以为接收端安全。详见 rsync 官方手册。
此外,原 -n 模拟没有 -i 或 -v,可能看不到足够的逐项变化;被排除的旧 /dev、/run、/tmp 内容也会留下。仅去掉 --delete 则会残留大量旧 Ubuntu 文件,尤其旧 /bin、/lib 等结构可能与 Arch 的符号链接冲突。
本文改为先在同一 ext4 内隔离旧内容,再 rsync 无删除复制。 这样能避免在嵌套源上运行删除同步;需要足够磁盘空间,并且中途失败后不能直接重启。
10.2 写入前关卡
以下只适用于“尚未替换,旧根仍是 Ubuntu”的机器。已经成功安装 Arch 的机器不要重跑第 10 节。
完成第 9 节的 ISO 释放检查后:1
2
3
4
5
6umount /mnt/target
mount -o rw /dev/vda3 /mnt/target
findmnt -M /mnt/target
findmnt -R /mnt/target
blkid /dev/vda3
df -h /mnt/target
此时目标下不得挂载 EFI 或其他子文件系统。findmnt -R /mnt/target 应只有目标本身。Bootstrap 的 /dev、/sys 等也不能仍有子挂载。若存在,先查清并正常卸载;本文不使用强制卸载。
剩余空间应大于安装源再复制一份所需空间,并留出包缓存、initramfs 和日志余量。原可用空间不能替代此时检查。
10.3 隔离旧 Ubuntu 文件
这是本手册新增的安全修订,并非原实例执行日志。使用 Live 的 Bash,核对每一项后执行。所有路径固定为本次目标,脚本通过条件检查后才移动文件:1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40bash <<'BASH'
set -euo pipefail
DST=/mnt/target
SRC=$DST/opt/arch-install/root.x86_64
OLD=$DST/.ubuntu-retired
mountpoint -q "$DST"
test "$(findmnt -n -o UUID -M "$DST")" = b4cbd348-1941-41f0-908b-42f34f456dcc
test "$(findmnt -Rrn -o TARGET "$DST" | wc -l)" -eq 1
test -d "$SRC/usr"
grep -qx 'ID=arch' "$SRC/etc/os-release"
grep -qx 'ID=ubuntu' "$DST/etc/os-release"
test -f "$SRC/boot/vmlinuz-linux"
test ! -e "$OLD"
test ! -L "$OLD"
test -d "$DST/opt" && test ! -L "$DST/opt"
test -d "$DST/boot" && test ! -L "$DST/boot"
mkdir "$OLD"
mkdir "$OLD/opt" "$OLD/boot"
shopt -s dotglob nullglob
# 保留安装源父目录、ISO 父目录和 ext4 lost+found;其余顶层内容隔离。
for path in "$DST"/*; do
name=${path##*/}
case "$name" in
opt|boot|.ubuntu-retired|lost+found) continue ;;
esac
mv -- "$path" "$OLD/"
done
for path in "$DST/opt"/*; do
case "${path##*/}" in arch-install) continue ;; esac
mv -- "$path" "$OLD/opt/"
done
for path in "$DST/boot"/*; do
case "${path##*/}" in iso|efi) continue ;; esac
mv -- "$path" "$OLD/boot/"
done
BASH
同一文件系统内 mv 通常只是目录项移动,不立即复制全部旧数据。这里保留 boot/efi 空挂载点,实际 EFI 此时必须未挂载。若保留路径有异常符号链接或旧内容,先检查,不盲目继续。
任一命令失败,停止并检查现场。脚本不是事务,不会自动回滚,也不能在隔离完成一半时直接重跑。此时 Ubuntu 已不完整,不能重启。 .ubuntu-retired 是临时隔离副本,不是独立备份;启动文件和 EFI 也不是完整原样快照。
10.4 无删除复制 Arch
以下在同一个 Live Bash shell 定义选项,模拟与正式复制使用同一组规则:1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17SRC=/mnt/target/opt/arch-install/root.x86_64
DST=/mnt/target
RSYNC_OPTS=(
-aHAXx --numeric-ids
--exclude='/opt/arch-install/***'
--exclude='/boot/iso/***'
--exclude='/boot/efi/***'
--exclude='/.ubuntu-retired/***'
--exclude='/dev/***'
--exclude='/proc/***'
--exclude='/sys/***'
--exclude='/run/***'
--exclude='/tmp/***'
--exclude='/mnt/***'
--exclude='/media/***'
)
rsync "${RSYNC_OPTS[@]}" --dry-run --itemize-changes "$SRC/" "$DST/"
确认源目标路径、无意外目录后执行:1
2rsync "${RSYNC_OPTS[@]}" --itemize-changes "$SRC/" "$DST/"
echo "rsync exit=$?"
应为退出码 0;出现 I/O 错误、空间不足、源文件消失或非零退出码,不能直接进入重启步骤。修复后可重试复制,但不要重新执行旧文件隔离脚本。
-aHAX 保留权限、链接、ACL 和扩展属性;--numeric-ids 按 UID/GID 保存属主;-x 不跨源子挂载,但不能替代挂载检查;"$SRC/" 尾随斜杠表示复制源内容。此处故意没有 --delete。
建立空的运行时目录并验收:1
2
3
4
5
6mkdir -p /mnt/target/{dev,proc,sys,run,tmp,mnt,media,boot/efi}
chmod 1777 /mnt/target/tmp
cat /mnt/target/etc/os-release
ls -ld /mnt/target/bin /mnt/target/sbin /mnt/target/lib /mnt/target/lib64
ls -lh /mnt/target/boot/vmlinuz-linux /mnt/target/boot/initramfs-linux.img
rsync "${RSYNC_OPTS[@]}" --dry-run --itemize-changes "$SRC/" "$DST/"
最终模拟应没有未解释的变化。安装后配置会有变化,后续不要为了“完全相同”再覆盖目标配置。保留安装源和旧文件隔离目录直到正式启动验证后再清理。
11. EFI 挂载、fstab、initramfs 和 GRUB(L → T)
11.1 挂载 EFI,生成 fstab(L)
1 | mkdir -p /mnt/target/boot/efi |
只保留现场需要的挂载,不得混入 Live ISO、loop、Bootstrap、自绑定或临时目录。本次核心应与以下一致:1
2UUID=b4cbd348-1941-41f0-908b-42f34f456dcc / ext4 defaults 0 1
UUID=4AA9-6FC3 /boot/efi vfat umask=0077 0 2
genfstab 生成的具体选项可能不同,应检查并按需要整理。生成用 > 覆盖而不是重复 >> 追加。UUID 以当前 blkid 为准;格式化后旧 UUID 不再可靠。
11.2 进入硬盘 Arch(T)
1 | arch-chroot /mnt/target |
如果目标未挂载,不要进入一个普通空目录;如果还显示 Ubuntu,回到迁移阶段检查,不能继续安装 Arch 引导。
11.3 内核和 initramfs
1 | ls -lh /boot/vmlinuz-linux |
检查生成是否成功,确认磁盘、根文件系统能力覆盖 Virtio 和 ext4。不要用 chroot 中的 uname -r 作为安装内核版本依据。
若存在自动探测遗漏风险,可在 /etc/mkinitcpio.conf 的现有 MODULES=(...) 中合并加入:1
MODULES=(virtio_pci virtio_blk ext4)
保留已有所需模块,不机械替换整行;修改后重新 mkinitcpio -P。本次磁盘是 Virtio block,换机器应按真实控制器确认所需模块。virtio_net 为联网能力,通常在根文件系统挂载后加载,不等同于根磁盘驱动。
11.4 安装 UEFI GRUB
确认 EFI 确实挂载在 /boot/efi,且 Live 以 UEFI 启动:1
2
3
4test -d /sys/firmware/efi
findmnt /boot/efi
grub-install --target=x86_64-efi \
--efi-directory=/boot/efi --bootloader-id=ArchLinux --recheck
200 MiB EFI 只放 GRUB EFI 文件,内核和 initramfs 放在 ext4 /boot,避免把整个 /boot 挂到小 EFI 分区。
编辑 /etc/default/grub,修改已有定义:1
2
3
4GRUB_DEFAULT=0
GRUB_TIMEOUT=5
GRUB_TIMEOUT_STYLE=menu
GRUB_CMDLINE_LINUX_DEFAULT="loglevel=3 net.ifnames=0 console=tty0 console=ttyS0,115200n8"
该参数保留原对话最后建议,去掉 quiet 方便首次排错;需要更多日志时可在控制台临时去掉 loglevel=3。1
2
3
4
5
6grub-mkconfig -o /boot/grub/grub.cfg
grub-script-check /boot/grub/grub.cfg
grep '^menuentry ' /boot/grub/grub.cfg
grep -E 'linux.*(vmlinuz|root=)' /boot/grub/grub.cfg
ls -lh /boot/efi/EFI/ArchLinux/grubx64.efi
efibootmgr -v
检查 GRUB 指向正确根 UUID、内核和 initramfs。仅存在一个名为 ArchLinux 的 EFI 条目不证明其文件和配置有效。
GRUB_DEFAULT=0 选择的是进入当前 GRUB 后的第一个菜单项;UEFI 是否先加载 ArchLinux 由 BootOrder/BootNext 决定,两者不能混为一谈。
12. systemd-networkd 和 DNS(B 或 T,最终在 T 复核)
1 | mkdir -p /etc/systemd/network |
记录里的 172.17.31.160/18 和 172.17.63.253 是租约,不写入静态配置。net.ifnames=0 必须确实进入最终内核命令行;若实际网卡不同,按实际名称修改配置。1
2
3cat /etc/systemd/network/20-eth0.network
readlink /etc/resolv.conf
systemctl is-enabled systemd-networkd systemd-resolved
chroot 中 DNS stub 链接可能暂时没有目标,因为目标 systemd-resolved 尚未运行;这不能直接等同于首次启动后 DNS 无效。如果 chroot 中需下载包,可临时使用 Live 的有效 DNS 文件,操作完成后恢复上述软链接。不要启动目标网络服务来“测试”,避免作用到宿主网络。
13. admin SSH 密码登录(T)
13.1 先确认配置落在硬盘系统
本次曾误查看 Live 的 /etc/ssh/sshd_config.d/10-archiso.conf,后续发现 /mnt/target 未挂载;重新挂载进入硬盘 Arch 后,目录仅有 20-systemd-userdb.conf 和 99-archlinux.conf。
因此,出现 10-archiso.conf 应先确认环境,不能直接认定硬盘被污染并删除 Live 配置。只有确认文件确实混入硬盘系统,备份并检查内容后才移除。
若丢失目标挂载,在 L 恢复:1
2
3
4
5
6mkdir -p /mnt/target
mount /dev/vda3 /mnt/target
cat /mnt/target/etc/os-release
mkdir -p /mnt/target/boot/efi
mount /dev/vda2 /mnt/target/boot/efi
arch-chroot /mnt/target
已挂载时不重复 mount。此恢复流程用于迁移已经完成的目标,不能代替系统迁移。
13.2 创建/确认用户与 sudo
1 | id admin |
仅不存在时执行:1
useradd -m -G wheel -s /bin/bash admin
然后:1
2
3passwd admin
passwd -S admin
getent passwd admin
密码状态应为 P,shell 不能为 nologin。密码由管理员交互输入,不写入文档。
如需管理权限,使用 visudo 安全编辑 sudo 配置,启用:1
%wheel ALL=(ALL:ALL) ALL
然后 visudo -c。原记录中的 EDITOR=visudo visudo 不合适;应直接 visudo,或 EDITOR=nano visudo。
13.3 SSH 配置
1 | pacman -Q openssh |
检查主配置是否包含有效的 Include /etc/ssh/sshd_config.d/*.conf,且位于适当的全局位置;检查更早配置及 Match 条件:1
2grep -RniE '^[[:space:]]*(Include|Match|PasswordAuthentication|PermitRootLogin|UsePAM|KbdInteractiveAuthentication|AllowUsers|DenyUsers|AuthenticationMethods)' \
/etc/ssh/sshd_config /etc/ssh/sshd_config.d/
OpenSSH 多数配置使用先取得的值,不能假定 99-... 总能覆盖前面文件;仅将文件改名为 00-... 也不能压过主文件在 Include 之前已设置的值。规则依据 OpenSSH 官方配置手册。
13.4 验证
1 | mkdir -p /run/sshd |
期望有效值,各占一行,顺序不限:1
2
3
4passwordauthentication yes
permitrootlogin no
usepam yes
kbdinteractiveauthentication no
保留用户在本次纠正的 grep -iE 写法,忽略大小写。sshd -T 通常输出小写;若没有匹配,不能只归因于大小写,应先不加管道运行 sshd -T 或 sshd -T 2>&1 检查报错。
如果有 Match,还要用 sshd -T -C 带真实 user=admin、客户端地址和相应连接条件检查。全局检查不能覆盖所有用户条件。
chroot 中 systemctl enable sshd 设置未来开机启动;systemctl start sshd 或 status 不能用于证明新系统服务已运行。实际监听与密码登录必须在 A 中验证。
密码登录按本次要求保留。使用强密码,控制公网 TCP 22 可访问范围;用户未要求切换密钥,本文不把关闭密码认证作为完成条件。
14. 重启前验收与正确重启(T → L)
逐项确认:
- 已确认目标根是
/dev/vda3上的 Arch,源文件复制完成且无未解决错误。 -
/etc/fstab的根/EFI UUID 与现场blkid一致,无 Live 临时挂载。 - 内核与 initramfs 非空,
mkinitcpio -P无致命错误,支持真实磁盘。 - EFI 挂载正确;GRUB EFI 文件、配置与根 UUID 一致。
-
eth0DHCP 文件正确,最终内核参数含net.ifnames=0。 - networkd、resolved、sshd 均为 enabled。
- admin 存在且密码状态为 P,SSH 语法和有效配置检查通过。
- 控制台可用,TCP 22 规则正确,记录了可信主机密钥指纹。
- 已识别真实 ArchLinux EFI 编号及首次启动选择。
可记录主机指纹用于客户端核对:1
ssh-keygen -lf /etc/ssh/ssh_host_ed25519_key.pub
先退出 T,再在 L 卸载:1
2
3
4
5exit
cd /
sync
umount -R /mnt/target
findmnt -R /mnt/target
最后检查不应有目标挂载。busy 时先关闭其他 chroot shell、离开目录,再用 fuser -vm /mnt/target 或 lsof 排查;不能强制或 lazy 卸载后当作成功。
检查 EFI:1
efibootmgr -v
找到真实 ArchLinux 启动号后设置一次性启动。下面是命令格式,XXXX 不是可执行的实际编号:1
efibootmgr -n XXXX
再次 efibootmgr 验证 BootNext。BootNext 仅影响下一次启动,后续稳定启动还需要正确的 BootOrder。原 0006 是 Ubuntu,原示例 0007 不能照搬。
全部满足后,在 Live 执行:1
reboot
不要在 chroot 中重启,也不要使用强制重启跳过同步与卸载。
15. 首次登录和持久启动验证(A)
在本地电脑用真实公网地址连接:1
ssh admin@你的服务器公网IP
若提示主机密钥变化,先在控制台核对第 14 节记录的指纹;核对无误后再清理客户端对应旧记录。不能直接关闭主机密钥校验。
登录后:1
2
3
4
5
6
7
8
9
10
11
12
13
14
15cat /etc/os-release
uname -r
findmnt /
findmnt /boot/efi
cat /proc/cmdline
ip -br addr
ip route
networkctl status eth0
resolvectl status
getent hosts archlinux.org
systemctl is-active sshd systemd-networkd systemd-resolved
systemctl --failed
sudo ss -lntp
sudo journalctl -b -p err
sudo efibootmgr -v
应确认 Arch、磁盘根 /dev/vda3、正常 IPv4 租约和默认路由、可解析 DNS、SSH 监听 TCP 22,且没有影响启动/联网的失败服务。通过公网成功密码登录是 admin SSH 的最终验证。
核对 BootCurrent 是 ArchLinux,并检查持久 BootOrder。若需调整,efibootmgr -o 使用真实编号并保留其他必要项;不要用固定示例覆盖全部顺序。建议在备份和控制台仍可用时再做一次受控重启,验证没有 BootNext 帮助也能正常从 Arch 启动。该二次验收是本文新增建议,原记录未保留二次重启输出。
最后做完整更新:1
sudo pacman -Syu
涉及内核/引导更新后,应根据更新结果安排验证,不在未确认网络和引导前盲目连环重启。
16. 安装残留清理(A,验收完成后)
可以暂时保留源、ISO 和隔离旧文件作为排错材料;它们含敏感信息,应限制访问。清理前确认当前系统确实从硬盘运行,并将所需数据移出服务器或恢复到新应用。1
2
3
4
5findmnt /
findmnt -R /opt/arch-install
findmnt -R /.ubuntu-retired
losetup -a
sudo du -sh /opt/arch-install /.ubuntu-retired /boot/iso
逐个核对实际绝对路径不是符号链接、内部无挂载、ISO 不再作 loop 后端,确认内容无需保留后,才可分别执行以下永久删除命令:1
2
3sudo rm -rf --one-file-system -- /opt/arch-install
sudo rm -rf --one-file-system -- /.ubuntu-retired
sudo rm -f -- /boot/iso/archlinux.iso
/.ubuntu-retired 仅由本文修订流程创建;若按原过程安装,可能不存在。--one-file-system 只是额外保护,不替代挂载检查(同一文件系统 bind mount 仍需排除)。
保留 Ubuntu EFI 文件不会恢复 Ubuntu。若后续需要移除旧 EFI 项或文件,先核对 BootCurrent、备份 EFI、确认不依赖其回退路径,再单独处理;不要批量删除整个 EFI 目录。新 GRUB 配置中也不应保留指向已删除 ISO 的默认启动项。
17. 故障排查
| 现象 | 优先检查 | 处理边界 |
|---|---|---|
| 下载 ISO 很慢/失败 | 镜像可达性、HTTP 状态、文件是否实际上是 HTML | 改可信镜像,重新验证版本和签名,不能只看文件名 |
| pacman 下载慢 | mirrorlist 是否一行一个 Server、DNS、HTTPS | 改阿里云/清华源,完整 pacman -Syu;已装 openssh 不必为了设置密码再同步数据库 |
core/extra 数据库不存在 | 是否尚未同步,pacman -Q openssh 是否有结果 | 本地包查询和仓库数据库是两回事;不关闭签名检查 |
| GRUB 找不到 ISO 内核 | ISO 是否下载完整、内部路径、根 UUID、isofile | 回旧系统检查 ISO 的 loopback.cfg,语法通过不等于可启动 |
| Live OOM / 无法复制到 RAM | free -h、实际 ISO 大小、copytoram 参数 | 换独立救援方案或增加可用内存,不以强制卸载代替 RAM 复制 |
| Live 根是 airootfs,但 vda3 仍被占用 | archiso 全部挂载及 loop 后端链 | 停止迁移,按第 9 节排查;不能仅 remount rw |
/mnt/target 未挂载 | mountpoint、findmnt -M | 挂载正确根分区,确认 Arch 后再 chroot;不重复格式化 |
| 目标仍显示 Ubuntu | 源目标路径、rsync 返回码、是否复制到错误目录 | 完成迁移后再装引导;不要通过改 os-release 伪造成功 |
| rsync 源文件消失 | 是否误用 –delete、源是否嵌套、目标/源是否颠倒 | 停止;保留现场,从备份恢复源,不立即重启 |
| rsync 空间不足 | df -h / df -i、源大小、隔离目录占用 | 保留可用安装源,改用独立存储或审慎释放已备份数据,不能盲删全部旧文件 |
mkinitcpio 失败 | /usr/lib/modules、内核包、磁盘驱动、/boot 容量 | 在目标 chroot 修复并重建,不沿用宿主 uname 推断 |
| EFI variables 不可用 | Live 是否 UEFI 启动、efivarfs、固件权限 | 修复 UEFI 访问条件;--no-nvram 只写文件不保证固件能找到 |
| 找不到 ArchLinux EFI 项 | grub-install 是否成功、ESP 是否实际挂载 | 核对文件及 NVRAM;不能只建一个名字当作修复完成 |
| 开机又进 Ubuntu/旧 GRUB | BootOrder、BootNext、BootCurrent | 调整真实 ArchLinux 项;GRUB_DEFAULT 不控制 EFI 层 |
| 开机没有网络 | 实际网卡名、/proc/cmdline、networkd 日志 | 确保 Name 匹配实际设备,DHCP 有租约和路由 |
| 有 IP 但无法解析域名 | resolved 状态、resolv.conf 链接、租约 DNS | 分别处理链路和 DNS,不写死旧私网租约 |
| SSH 拒绝连接/超时 | 控制台是否已启动、22 入站、sshd 监听及网络 | 区分网络超时、无监听与认证失败 |
| SSH 密码认证失败 | passwd -S、有效配置、Match/AllowUsers/PAM、日志 | 在硬盘目标修复;Live 的密码和配置不能验证硬盘账号 |
sshd -T | grep 无输出 | 先执行无管道 sshd -T、看错误流 | 使用用户确认的 -iE;仍无结果则查语法/密钥/环境 |
| sshd 目录出现 10-archiso.conf | 当前是 L 还是 T | 不自动删除 Live 配置;先进入正确硬盘系统 |
| chroot systemctl 提示未运行 systemd | 当前环境是否 T/B | enable 可配置未来启动;active/status 只在 A 作最终验收 |
| 卸载 target busy | shell 当前目录、其他 chroot、进程、ISO 链 | cd /、退出其他 shell,排查后正常卸载,不强制 |
在正式 Arch 的控制台排查网络/SSH:1
sudo journalctl -b -u systemd-networkd -u systemd-resolved -u sshd
若无法从硬盘启动,从可用 Live/救援环境挂载根和 EFI,核对目标 os-release 后进入 T,重建 initramfs、GRUB 并复核 fstab。无需因 SSH 不通就立即重装整个系统。
18. 相对最初方案的修正
- 替换嵌套源
rsync --delete:采用旧文件隔离 + 无删除复制,避免源被接收端删除,旧目录与符号链接结构也先移开。 - 模拟同步加可见输出:使用
--dry-run --itemize-changes,不能把“没看到输出”当作删除清单安全。 - 严格检查 ISO 依赖链:copytoram 参数和 airootfs 不是分区已释放的证据;loop 是否安全取决于后端位置。
- 区分 Live 和 chroot:验证目标实际挂载及 os-release,再配置硬盘 SSH;不把 Live 的 10-archiso.conf 当作目标必然污染。
- 恢复配置换行:GRUB、networkd、mirrorlist、sshd 配置各指令单独一行,避免导出文本的一行粘贴错误。
- 校验值标注来源:保留原 ISO SHA256,但不把未经独立核实的历史值当作可信发布校验。
- 不固化租约/示例编号:IP 和网关继续 DHCP;0007 仅示例;最终 EFI 编号现场取得。
- 修正 sudo 编辑方式:用 visudo 或 EDITOR=nano visudo,不使用 EDITOR=visudo visudo。
- 不在 chroot 验证服务运行或重启:只配置 enable,退出后从 Live 正常卸载重启,再检查服务 active。
- 增加持久启动验收:BootNext 仅一次;确认 BootOrder 并做受控二次启动后再删除安装材料。
19. 参考资料与使用说明
- 本次迁移的现场记录:实际参数、过程顺序、遇到的问题,以及最终从硬盘启动的结果。截图外链不能当作可读附件。
- Arch Linux 官方下载:发布介质和验证资料入口。
- rsync 官方手册:同步、过滤及删除保护语义。
- OpenSSH 官方 sshd_config 手册:配置读取顺序和认证选项;Linux 的 UsePAM 以安装版本本地手册为准。
- ArchWiki:从现有 Linux 安装 Arch、GRUB、OpenSSH:原对话参考入口;整理时页面访问受到站点限制,未将无法读取的页面当成新增事实证明。
本手册描述历史成功迁移及经过审查的操作建议,不承诺镜像地址永远可用或所有轻量服务器都支持相同启动流程。具体工具行为以当前安装版本的本地手册和现场检查为准。