一、前言
这是一个用于让AI自动帮你最小安装Arch Linux的工作流程,对此你只需要做下面几件事即可让AI帮你安装Arch Linux
0.除了要安装Arch的电脑外,你还需要一台电脑,或者任意可以运行agent(codex,claude code等)的设备
1.制作系统U盘
2.进入安装引导
3.在安装引导中配置好网络(无线有线皆可)
4.让你的具有工具的电脑与被安装电脑在同一局域网
5.在安装引导中获取IP地址
6.设置安装引导中root的密码
7.将下方MD文档内容复制一份到本地文档
8.告诉你熟悉的agent文档路径与你安装引导中获取到的IP地址以及root密码,等待安装完成
注意:
本次安装会清空你的磁盘,如果你需要双系统,需要对AI进行特殊说明
使用本SKILL需要一定的基础\
你需要有操作agent的经验
二、SKILL文档
bash
# Arch Linux 从零安装到可启动的完整实战文档
本文基于一次真实的 Arch Linux 远程安装与救援过程整理,不是只讲"标准答案",而是把实际会踩到的坑、为什么会踩、怎么避免、踩了以后怎么修,都写进去。
目标是让你看完以后,能够:
- 从 Arch ISO 开始,独立完成一次 UEFI + GPT + Btrfs 的安装
- 正确理解 ESP、`/boot`、`/boot/efi`、GRUB、`systemd-boot` 之间的关系
- 知道为什么"装好了包"不等于"能启动"
- 知道远程安装时,怎样避免重启后失联
- 知道启动失败以后,应该从哪里下手修
本文使用中文,并尽量用"能直接照做"的方式写。
---
## 1. 本文适用场景
本文最适合下面这种机器和需求:
- 机器使用 UEFI 启动
- 磁盘分区表使用 GPT
- 根分区使用 Btrfs
- ESP 单独分区,挂载到 `/boot/efi`
- 你希望使用 GRUB 作为启动器
- 你可能需要通过 SSH 远程安装或远程救援
- 你是笔记本,可能需要 Wi-Fi 才能联网
本文也适合"系统已经装了一半,但启动坏了"的情况,因为后面专门有修复流程。
---
## 2. 这次真实机器的最终工作配置
先把这次实机最终跑通的配置列出来,后面很多命令都围绕它展开。
### 2.1 磁盘与文件系统
- 磁盘:`/dev/nvme0n1`
- 分区 1:`/dev/nvme0n1p1`
- 类型:ESP
- 大小:512 MiB
- 文件系统:FAT32
- 挂载点:`/boot/efi`
- 分区 2:`/dev/nvme0n1p2`
- 类型:swap
- 大小:8 GiB
- 分区 3:`/dev/nvme0n1p3`
- 类型:Btrfs
- 标签:`Arch`
- 子卷:
- `@` 挂载到 `/`
- `@home` 挂载到 `/home`
### 2.2 启动方式
- 固件模式:UEFI
- 启动器:GRUB
- EFI 文件路径:
- `\EFI\MyArch\grubx64.efi`
- `\EFI\Boot\bootx64.efi` 作为 fallback
- UEFI 启动项:`Boot0000* MyArch`
### 2.3 系统与网络
- 主机名:`MyArch`
- 内核:`linux`
- 微码:`intel-ucode`
- 远程访问:`openssh` + `sshd`
- 无线网络:`iwd`
- IP 配置:`systemd-networkd`
- DNS:`systemd-resolved`
### 2.4 这次最关键的坑
这次真正把系统搞坏的,不是"没装内核",也不是"没写引导项",而是:
- ESP 实际挂载在 `/boot/efi`
- 内核和 initramfs 实际在根文件系统的 `/boot`
- 但原来的 `systemd-boot` 条目却写成了从 ESP 根目录找 `/vmlinuz-linux`、`/initramfs-linux.img`
结果就是:
- 文件明明存在
- `bootctl` 明明也在
- 但是启动条目实际指向了错误位置
- 最终表现为"看上去都装了,但就是起不来"
这是本文最重要的经验之一。
---
## 3. 安装前必须先想清楚的三件事
很多人安装 Arch 失败,不是命令不会敲,而是这三件事没在开工前想清楚。
### 3.1 你到底是 BIOS 还是 UEFI
先确认:
```bash
ls /sys/firmware/efi/efivars
```
如果目录存在,说明你当前是 UEFI 模式启动的。
更直接一点:
```bash
if [ -d /sys/firmware/efi/efivars ]; then
echo UEFI
else
echo BIOS
fi
```
为什么这一步很重要:
- UEFI 和 BIOS 的启动器安装方式不同
- UEFI 需要 ESP
- BIOS 通常不需要 ESP
- 你如果在 UEFI 机器上按 BIOS 思路装,或者反过来,后面很容易白干
### 3.2 你到底想把 ESP 挂在哪里
UEFI 机器上最常见的两种做法:
1. 把 ESP 挂到 `/boot`
2. 把 ESP 挂到 `/boot/efi`
这两种做法都可以,但后果不同。
#### 做法 A:ESP 挂到 `/boot`
优点:
- `systemd-boot` 用起来最顺手
- 内核、initramfs、微码直接放在 ESP 上,路径简单
缺点:
- ESP 是 FAT32,不支持 Unix 权限和很多 Linux 特性
- `/boot` 上所有东西都放到 FAT32,不是所有人都喜欢
#### 做法 B:ESP 挂到 `/boot/efi`
优点:
- `/boot` 仍然在 Linux 文件系统里
- 内核和 initramfs 不必放在 FAT32
- 和很多发行版的默认习惯更接近
缺点:
- 如果你还想用 `systemd-boot`,就必须非常清楚内核文件到底在 ESP 上还是不在
- 你不能想当然地写 `linux /vmlinuz-linux`,除非那个文件真的在 ESP 根目录
这次我们最终选择的是:
- `/boot` 在 Btrfs 根文件系统里
- ESP 挂在 `/boot/efi`
- 启动器用 GRUB
这是一个非常稳的组合。
### 3.3 你到底想用什么网络方案
大多数桌面笔记本用户有两个常见选择:
#### 方案 A:`NetworkManager`
优点:
- 最省心
- 对桌面、笔记本、Wi-Fi、图形界面最友好
- 重启后网络恢复通常比较简单
缺点:
- 对"纯手工控制"用户来说会稍重一点
#### 方案 B:`iwd + systemd-networkd + systemd-resolved`
优点:
- 纯净
- 可控
- 适合远程、服务器风格、手工管理
缺点:
- 你必须自己确保 Wi-Fi profile、networkd 配置、DNS 配置都落到目标系统里
- 少一步都可能导致"系统能启动,但重启后没网,SSH 连不上"
这次为了保证远程重启后尽量能自己回网,我们最终使用的是方案 B。
如果你只是本地安装、后续要装桌面环境,通常 `NetworkManager` 更省事。
---
## 4. 准备工作
### 4.1 你需要准备什么
- Arch Linux 启动 U 盘
- 能进入 BIOS/Boot Menu
- 明确知道目标磁盘是哪块
- 如果你要远程装机:
- 机器必须先联网
- 你要有另一台机器能 SSH 进去
- 你要能在现场看屏幕,或者有人在机器旁边
### 4.2 BIOS 里建议先确认
- 启动模式是 UEFI
- Secure Boot 是否关闭
- 启动顺序里允许从 U 盘启动
如果你不确定 Secure Boot 状态,在 Arch ISO 里也可以看:
```bash
bootctl status
```
如果看到 `Secure Boot: disabled`,那就和这次实机一致。
---
## 5. 进入 Arch ISO 后的第一批检查
启动进 Arch ISO 之后,不要马上分区,先做检查。
### 5.1 确认时间同步
```bash
timedatectl set-ntp true
timedatectl status
```
时间不准会影响很多事,比如包管理、TLS、日志判断。
### 5.2 确认网络
#### 有线网络
通常插上就有,直接看:
```bash
ip -br a
ip route
ping -c 3 archlinux.org
```
#### Wi-Fi 网络
用 `iwctl`:
```bash
iwctl
device list
station wlan0 scan
station wlan0 get-networks
station wlan0 connect <你的SSID>
exit
```
然后再检查:
```bash
ip -br a
ping -c 3 archlinux.org
```
### 5.3 如果你要远程安装
先在 live 环境设置 root 密码并启动 SSH:
```bash
passwd
systemctl start sshd
ip -br a
```
然后从另一台机器登录:
```bash
ssh root@<live环境的IP>
```
这次实际操作就是先远程连进 live 环境,再继续排查和 chroot。
---
## 6. 识别磁盘,别装错盘
先看磁盘:
```bash
lsblk -f
blkid
```
重点看:
- 哪块是 U 盘
- 哪块是内置 NVMe/SSD
- 之前有没有 Windows 分区
- 有没有已经存在的 ESP
- 有没有已有的 Linux 分区
这次实机里看到的是:
- `sda`:Arch ISO U 盘
- `nvme0n1`:内部系统盘
绝对不要看到 `sda` 就直接分。很多人第一步就把安装 U 盘自己格式化了。
---
## 7. 推荐分区方案
这里给出和这次实机一致、比较稳的方案。
### 7.1 分区布局
- `p1`:ESP,512 MiB,FAT32
- `p2`:swap,8 GiB
- `p3`:Btrfs,占剩余全部空间
### 7.2 用 `cfdisk` 手工分区
如果你更喜欢交互式:
```bash
cfdisk /dev/nvme0n1
```
选择:
- 分区表:GPT
- 建立 512 MiB EFI System 分区
- 建立 8 GiB Linux swap 分区
- 剩余空间建立 Linux filesystem 分区
### 7.3 用 `parted` 非交互分区
如果你喜欢可复制命令:
```bash
parted /dev/nvme0n1 --script mklabel gpt
parted /dev/nvme0n1 --script mkpart ESP fat32 1MiB 513MiB
parted /dev/nvme0n1 --script set 1 esp on
parted /dev/nvme0n1 --script mkpart primary linux-swap 513MiB 8705MiB
parted /dev/nvme0n1 --script mkpart primary btrfs 8705MiB 100%
```
分完再次确认:
```bash
lsblk -f
parted /dev/nvme0n1 print
```
---
## 8. 格式化文件系统
### 8.1 格式化 ESP
```bash
mkfs.fat -F32 /dev/nvme0n1p1
```
### 8.2 初始化 swap
```bash
mkswap /dev/nvme0n1p2
swapon /dev/nvme0n1p2
```
### 8.3 格式化 Btrfs
```bash
mkfs.btrfs -L Arch /dev/nvme0n1p3
```
---
## 9. 创建 Btrfs 子卷并正确挂载
这一步非常关键。
### 9.1 先挂顶层,再创建子卷
```bash
mount /dev/nvme0n1p3 /mnt
btrfs subvolume create /mnt/@
btrfs subvolume create /mnt/@home
umount /mnt
```
### 9.2 重新按目标布局挂载
```bash
mount -o subvol=@,compress=zstd:3,ssd,discard=async /dev/nvme0n1p3 /mnt
mkdir -p /mnt/home
mkdir -p /mnt/boot/efi
mount -o subvol=@home,compress=zstd:3,ssd,discard=async /dev/nvme0n1p3 /mnt/home
mount /dev/nvme0n1p1 /mnt/boot/efi
```
### 9.3 验证挂载结果
```bash
findmnt -R /mnt
```
你希望看到的是类似:
- `/mnt` 来自 `subvol=@`
- `/mnt/home` 来自 `subvol=@home`
- `/mnt/boot/efi` 来自 ESP
### 9.4 这一步最常见的坑
#### 坑 1:以为系统已经挂了,其实 `/mnt` 是空的
这次真实排查时,一开始 `/mnt` 根本就是空的,说明目标系统压根没挂上去。
判断方式:
```bash
findmnt -R /mnt
ls -la /mnt
```
如果只看到空目录,就别急着 chroot,更别急着装引导。
#### 坑 2:把 ESP 挂到 `/mnt/boot`,后来 `fstab` 却写成 `/boot/efi`
这会直接埋雷。
你必须全程统一:
- 你决定 ESP 挂到哪里
- 就一路保持一致
- `fstab`、启动器、路径、验证命令都要用同一套逻辑
---
## 10. 安装基础系统
### 10.1 推荐安装包
如果你按本文路线走,建议安装这些包:
```bash
pacstrap -K /mnt \
base \
linux \
linux-firmware \
btrfs-progs \
grub \
efibootmgr \
sudo \
vim \
openssh \
iwd \
intel-ucode
```
如果你是 AMD CPU,把 `intel-ucode` 换成 `amd-ucode`。
如果你更想走 `NetworkManager` 路线,可以额外装:
```bash
pacstrap -K /mnt networkmanager
```
### 10.2 生成 `fstab`
```bash
genfstab -U /mnt > /mnt/etc/fstab
cat /mnt/etc/fstab
```
注意这里我故意用的是 `>` 而不是 `>>`。
#### 为什么这里要强调
这次实机遇到过一个非常典型的坑:
- 同一个根分区和 home 分区被重复写进了 `fstab`
- 结果 `fstab` 里出现了两份 `/`、两份 `/home`
这种问题往往来自:
- 多次执行 `genfstab -U /mnt >> /mnt/etc/fstab`
- 每次都 append,没有先清掉旧内容
所以:
- 第一次生成时优先用 `>`
- 如果你需要重生成,先人工审查
### 10.3 推荐的 `fstab` 目标样子
如果你按本文的方案,最终应该类似:
```fstab
# /dev/nvme0n1p3 LABEL=Arch
UUID=<btrfs-uuid> / btrfs rw,relatime,compress=zstd:3,ssd,discard=async,space_cache=v2,subvol=/@ 0 0
# /dev/nvme0n1p3 LABEL=Arch
UUID=<btrfs-uuid> /home btrfs rw,relatime,compress=zstd:3,ssd,discard=async,space_cache=v2,subvol=/@home 0 0
# /dev/nvme0n1p1
UUID=<esp-uuid> /boot/efi vfat rw,relatime,fmask=0022,dmask=0022,codepage=437,iocharset=ascii,shortname=mixed,utf8,errors=remount-ro 0 2
# /dev/nvme0n1p2
UUID=<swap-uuid> none swap defaults 0 0
```
---
## 11. 进入 chroot,开始真正配置系统
```bash
arch-chroot /mnt
```
进去以后,按下面顺序配置。
### 11.1 时区
```bash
ln -sf /usr/share/zoneinfo/Asia/Shanghai /etc/localtime
hwclock --systohc
```
### 11.2 本地化
编辑:
```bash
vim /etc/locale.gen
```
取消注释至少这两行:
```text
en_US.UTF-8 UTF-8
zh_CN.UTF-8 UTF-8
```
生成 locale:
```bash
locale-gen
```
写入:
```bash
cat > /etc/locale.conf <<'EOF'
LANG=zh_CN.UTF-8
EOF
```
### 11.3 主机名
```bash
cat > /etc/hostname <<'EOF'
MyArch
EOF
```
### 11.4 `/etc/hosts`
```bash
cat > /etc/hosts <<'EOF'
127.0.0.1 localhost
::1 localhost
127.0.1.1 MyArch.localdomain MyArch
EOF
```
### 11.5 root 密码
```bash
passwd
```
### 11.6 创建普通用户
```bash
useradd -m -G wheel -s /usr/bin/bash archuser
passwd archuser
```
### 11.7 开启 sudo
推荐方式是 `visudo`,但如果你就是想快速自动化:
```bash
sed -i 's/^# %wheel ALL=(ALL:ALL) ALL/%wheel ALL=(ALL:ALL) ALL/' /etc/sudoers
```
验证:
```bash
grep '^%wheel ALL=(ALL:ALL) ALL' /etc/sudoers
```
---
## 12. 选择并配置网络方案
这一节非常重要,因为"系统能启动"和"系统启动后能联网"是两回事。
---
### 12.1 方案 A:`NetworkManager`,适合大多数桌面用户
安装:
```bash
pacman -S networkmanager
systemctl enable NetworkManager
```
优点是重启后本地用 `nmtui` 或桌面网络管理器很好配。
如果你是本地装机,而且不依赖远程 SSH 回连,这是最省事的选择。
---
### 12.2 方案 B:`iwd + systemd-networkd + systemd-resolved`,适合手工控制和远程续连
这次实机最终使用的就是这一套。
#### 安装
```bash
pacman -S iwd openssh
```
#### 启用服务
```bash
systemctl enable iwd
systemctl enable systemd-networkd
systemctl enable systemd-resolved
systemctl enable sshd
```
#### `resolv.conf`
```bash
rm -f /etc/resolv.conf
ln -s /run/systemd/resolve/stub-resolv.conf /etc/resolv.conf
```
#### `networkd` 配置
创建 `/etc/systemd/network/20-wlan.network`:
```ini
[Match]
Type=wlan
[Link]
RequiredForOnline=routable
[Network]
DHCP=yes
MulticastDNS=yes
[DHCPv4]
RouteMetric=600
[IPv6AcceptRA]
RouteMetric=600
```
如果你还要给有线网卡准备自动 DHCP,再加 `/etc/systemd/network/20-ethernet.network`:
```ini
[Match]
Type=ether
Kind=!*
[Link]
RequiredForOnline=routable
[Network]
DHCP=yes
MulticastDNS=yes
[DHCPv4]
RouteMetric=100
[IPv6AcceptRA]
RouteMetric=100
```
#### Wi-Fi 配置怎么持久化
如果你是本地安装,首次开机后直接用:
```bash
iwctl
station wlan0 scan
station wlan0 get-networks
station wlan0 connect <你的SSID>
```
`iwd` 会在 `/var/lib/iwd/` 里生成对应 profile。
如果你是远程安装,并且当前 live 环境已经连上了 Wi-Fi,那么最稳的办法是:
```bash
cp -f /var/lib/iwd/<你的SSID>.psk /mnt/var/lib/iwd/
chmod 600 /mnt/var/lib/iwd/<你的SSID>.psk
```
这样重启后目标系统就有现成的 Wi-Fi profile 了。
#### 不要让两套网络栈抢同一个无线网卡
如果你最终决定用 `iwd + networkd`,那就不要同时让 `NetworkManager` 启用:
```bash
systemctl disable NetworkManager
```
这次实机最终就是这么处理的。
---
## 13. 为什么这次最终选择 GRUB,而不是 systemd-boot
这一节是本文最有价值的部分之一。
### 13.1 先说结论
在这次的目录结构下:
- ESP 挂载到 `/boot/efi`
- 内核、微码、initramfs 位于根文件系统 `/boot`
最稳的选择是 GRUB。
### 13.2 `systemd-boot` 什么时候最舒服
当你满足下面任一条件时,`systemd-boot` 会比较顺手:
1. 你把 ESP 直接挂到 `/boot`
2. 你使用 UKI,并且 UKI 放在 ESP 上
3. 你明确管理好内核、微码、initramfs 到 ESP 的复制和路径
### 13.3 这次为什么原来的 `systemd-boot` 会坏
原来的状况是:
- `fstab` 写的是 ESP 挂载到 `/boot/efi`
- 但 `loader/entries/arch.conf` 里写的是:
```text
linux /vmlinuz-linux
initrd /intel-ucode.img
initrd /initramfs-linux.img
```
对于 `systemd-boot` 来说,这些路径是相对于 ESP 的。
可问题是:
- ESP 根本没有这些文件
- 这些文件实际在根文件系统里的 `/boot`
所以 `bootctl status` 直接会报类似:
- `linux: /boot//vmlinuz-linux (No such file or directory)`
- `initrd: /boot//intel-ucode.img (No such file or directory)`
这不是 `systemd-boot` 坏了,而是路径设计和挂载点逻辑错位了。
### 13.4 GRUB 为什么能解决这个问题
GRUB 能很好处理:
- UEFI ESP 只放 GRUB EFI 文件
- 内核和 initramfs 放在 Linux 根文件系统
- 根文件系统还是 Btrfs 子卷
它生成出来的条目可以直接指向:
```text
/@/boot/vmlinuz-linux
/@/boot/intel-ucode.img
/@/boot/initramfs-linux.img
```
这正是这次重启成功的关键。
---
## 14. 正确安装 GRUB 的完整步骤
进入 chroot 后:
### 14.1 先生成 initramfs
```bash
mkinitcpio -P
```
### 14.2 安装 GRUB 到 UEFI
```bash
grub-install --target=x86_64-efi --efi-directory=/boot/efi --bootloader-id=MyArch --recheck
```
### 14.3 再写 fallback 路径
这一步很重要,很多人会省略。
```bash
grub-install --target=x86_64-efi --efi-directory=/boot/efi --removable --no-nvram --recheck
```
它会把 EFI 文件写到:
```text
\EFI\Boot\bootx64.efi
```
有什么用:
- 某些固件不认你新建的 NVRAM 项
- 某些固件更新、清 CMOS、重置后会丢 NVRAM
- fallback 路径能兜底
### 14.4 生成 `grub.cfg`
```bash
grub-mkconfig -o /boot/grub/grub.cfg
```
### 14.5 检查语法
```bash
grub-script-check /boot/grub/grub.cfg
```
### 14.6 检查 UEFI 启动项
```bash
efibootmgr -v
```
你希望看到类似:
```text
Boot0000* MyArch HD(...) \EFI\MyArch\grubx64.efi
BootOrder: 0000,...
```
如果新建项没有被放到前面,可以自己调:
```bash
efibootmgr -o 0000,0007,0002,0003
```
这里的编号按你机器实际输出改。
---
## 15. 重启前必须做的验收
这一步非常重要。
在你敲 `reboot` 之前,至少检查以下内容。
### 15.1 挂载是否正确
```bash
findmnt / /boot/efi /home
```
### 15.2 内核与 initramfs 是否真的存在
```bash
ls -lh /boot/vmlinuz-linux /boot/intel-ucode.img /boot/initramfs-linux.img
```
### 15.3 `grub.cfg` 是否存在
```bash
ls -lh /boot/grub/grub.cfg
```
### 15.4 UEFI 文件是否存在
```bash
ls -lh /boot/efi/EFI/MyArch/grubx64.efi
ls -lh /boot/efi/EFI/Boot/bootx64.efi
```
### 15.5 SSH host key 是否存在
如果你依赖远程回连,强烈建议手动生成:
```bash
ssh-keygen -A
ls -l /etc/ssh/ssh_host_*_key
```
否则有可能发生:
- `sshd` 虽然 enabled
- 但首次开机时没把 host keys 及时准备好
- 结果 SSH 起不来
### 15.6 网络服务是否启用
如果你用的是本文的 `iwd + networkd` 路线:
```bash
systemctl is-enabled iwd
systemctl is-enabled systemd-networkd
systemctl is-enabled systemd-resolved
systemctl is-enabled sshd
```
### 15.7 `root` 密码设了,不代表 `root` 可以 SSH 登录
这是这次实机又一个非常典型的点。
这次最终表现是:
- `root` 本地密码是正确的
- 但是 SSH 用 `root` 密码登录被拒绝
- `archuser` 可以正常 SSH 登录
原因通常不是密码错,而是 SSH 策略不允许 root 密码登录。
所以远程验收时,不要只盯着 `root`,普通用户 + `sudo` 往往更稳。
---
## 16. 正确重启的方法
如果你在本机本地操作,推荐:
```bash
exit
umount -R /mnt
swapoff -a
reboot
```
如果你是远程操作,有时未必方便完全按这个顺序做,但你要知道副作用。
### 16.1 这次实机重启后的一个小后果
因为这次是在 live 环境中远程修完后直接重启,ESP 后来出现了一条警告:
```text
FAT-fs (nvme0n1p1): Volume was not properly unmounted.
```
这说明 ESP 不是完全干净卸载的。
它没有导致启动失败,但会留下 FAT dirty-bit 警告。
这类问题一般后续维护窗口再修:
```bash
fsck.vfat -a /dev/nvme0n1p1
```
所以经验是:
- 本地安装时,尽量规范卸载再重启
- 远程抢救时,功能优先,dirty-bit 警告可以后面收尾
---
## 17. 首次启动后的验收步骤
### 17.1 看系统是否真的不是 live 环境
```bash
hostnamectl
cat /etc/os-release
```
你应该看到:
- 主机名是你自己设的
- 不是 `archiso`
- 内核版本是你安装到磁盘里的系统版本
### 17.2 看 UEFI 当前到底是从哪个项目启动的
```bash
sudo efibootmgr -v
```
这次实机重启成功后的关键证据是:
```text
BootCurrent: 0000
Boot0000* MyArch ...
```
这说明固件不是"碰巧走了 fallback",而是真的从我们创建的 `MyArch` 启动项起来的。
### 17.3 看网络和 SSH
```bash
systemctl is-active iwd systemd-networkd systemd-resolved sshd
systemctl is-enabled iwd systemd-networkd systemd-resolved sshd
ip -br a
```
如果是 Wi-Fi:
```bash
iwctl station wlan0 show
```
### 17.4 看挂载
```bash
findmnt / /boot/efi /home
```
### 17.5 看有没有明显故障
```bash
systemctl --failed
journalctl -b -p warning --no-pager
```
---
## 18. 这次真实踩坑记录与经验总结
下面是这次最有代表性的坑。
### 坑 1:以为 `/mnt` 里就是已安装系统,结果其实没挂
现象:
- `arch-chroot /mnt` 进去可能是空的、错的,甚至根本进不去
- 你以为自己在改目标系统,实际上改的是 live 环境
正确做法:
```bash
findmnt -R /mnt
ls -la /mnt
```
只有确认:
- `/mnt` 真挂着目标根
- `/mnt/home` 真挂着 home 子卷
- `/mnt/boot/efi` 真挂着 ESP
后续操作才有意义。
### 坑 2:Btrfs 子卷名要先确认,别想当然
这次实际看到的是:
- `@`
- `@home`
不是所有系统都这么命名。
所以先看:
```bash
mount -o subvolid=5 /dev/nvme0n1p3 /mnt
btrfs subvolume list /mnt
umount /mnt
```
确认完再挂。
### 坑 3:`systemd-boot` 条目和真实挂载点不一致
这是本次核心问题。
错误本质:
- `fstab`:ESP 挂 `/boot/efi`
- 启动条目:假设内核在 ESP 根目录
- 实际:内核在 Linux 根文件系统的 `/boot`
这类问题最可怕的地方在于:
- 包都装了
- 文件都在
- `bootctl` 也在
- 甚至 ESP 上看起来也有 `loader/entries/arch.conf`
- 但它仍然会启动失败
经验:
- 启动器不是看"文件有没有",而是看"路径逻辑是否闭环"
### 坑 4:`fstab` 重复条目
原因通常是反复 append `genfstab`。
后果:
- 挂载行为混乱
- 排查时很容易误判
经验:
- 生成 `fstab` 时优先 `>`
- 重生成前先清楚旧内容
- 最终一定手工审一遍
### 坑 5:只装了 `sshd`,没保证重启后真能远程进
想让远程重启后还能接回来,至少要同时满足:
- `openssh` 已安装
- `sshd` 已启用
- host keys 已存在
- 网络配置已落盘
- Wi-Fi profile 已落盘
- DNS 正常
少任何一步,都可能变成:
- 系统其实启动成功了
- 但你就是连不上
### 坑 6:`root` 密码可用,不代表 root SSH 一定可用
这次实机重启后就是:
- `archuser` 可 SSH 登录
- `root` 密码 SSH 被拒绝
这说明要区分三件事:
1. root 账户是否存在
2. root 密码是否设好
3. SSH 策略是否允许 root 密码登录
不要把这三件事混成一件。
### 坑 7:远程安装时,网络栈千万别双开
如果你最后要用:
- `iwd + systemd-networkd`
那就不要再让:
- `NetworkManager`
同时接管无线网卡。
不然经常会出现:
- live 环境里明明联网
- 装好后第一次开机网络状态异常
- 接口被抢、配置混乱
### 坑 8:日志里的 `nouveau` 警告容易吓人,但它不是这次的启动主因
这次重启后的 `journalctl -b -p warning` 里有大量 `nouveau` 的 GSP 报错。
它说明的是:
- 这台带 NVIDIA 显卡的机器,开源 `nouveau` 驱动存在兼容性或功能问题
但注意:
- 这不是引导失败的原因
- 不是 GRUB 坏了
- 不是 ESP 坏了
经验:
- 启动器问题和显卡驱动问题要分开看
---
## 19. 如果启动失败,怎么救
这一节非常重要。
你如果重启后起不来,不要慌,按下面顺序来。
### 19.1 先观察失败停在哪一层
#### 情况 A:固件直接进回 BIOS / Boot Menu
优先怀疑:
- 没有正确 EFI 文件
- UEFI 启动项没写进去
- BootOrder 不对
检查:
- BIOS 里是否能看到 `MyArch`
- 有没有 fallback 路径
#### 情况 B:能进 GRUB,但选内核后失败
优先怀疑:
- `grub.cfg` 条目路径不对
- 根 UUID 不对
- `rootflags=subvol=@` 不对
- initramfs 缺失
#### 情况 C:内核起来了,但卡在挂载根文件系统
优先怀疑:
- `fstab` 错
- Btrfs 子卷名错
- UUID 错
#### 情况 D:系统其实启动成功,但你远程连不上
优先怀疑:
- Wi-Fi profile 没落盘
- `iwd` / `networkd` / `resolved` / `sshd` 没 enable
- SSH host keys 没生成
### 19.2 通用修复流程
重新用 Arch ISO 启动,联网后:
```bash
mount -o subvol=@ /dev/nvme0n1p3 /mnt
mkdir -p /mnt/home /mnt/boot/efi
mount -o subvol=@home /dev/nvme0n1p3 /mnt/home
mount /dev/nvme0n1p1 /mnt/boot/efi
swapon /dev/nvme0n1p2
arch-chroot /mnt
```
### 19.3 修 `fstab`
```bash
cat /etc/fstab
```
确认:
- `/` 是 `subvol=/@`
- `/home` 是 `subvol=/@home`
- ESP 是 `/boot/efi`
- 没有重复条目
### 19.4 重新生成 initramfs
```bash
mkinitcpio -P
```
### 19.5 重装 GRUB
```bash
grub-install --target=x86_64-efi --efi-directory=/boot/efi --bootloader-id=MyArch --recheck
grub-install --target=x86_64-efi --efi-directory=/boot/efi --removable --no-nvram --recheck
grub-mkconfig -o /boot/grub/grub.cfg
grub-script-check /boot/grub/grub.cfg
efibootmgr -v
```
### 19.6 修 ESP 的 FAT dirty-bit
如果日志里提示 ESP 没有正常卸载:
先在 live 环境卸载它,然后:
```bash
fsck.vfat -a /dev/nvme0n1p1
```
### 19.7 修远程网络
如果系统启动了但连不回去:
```bash
pacman -S openssh iwd
systemctl enable sshd
systemctl enable iwd
systemctl enable systemd-networkd
systemctl enable systemd-resolved
ssh-keygen -A
```
确认:
```bash
ls -l /var/lib/iwd
ls -l /etc/systemd/network
ls -l /etc/ssh/ssh_host_*_key
```
---
## 20. 推荐的最小可行安装命令清单
如果你只想看一版能直接复制的最小流程,这里给一份浓缩版,但你最好结合前文理解它。
### 20.1 live 环境
```bash
timedatectl set-ntp true
```
联网后分区、格式化、挂载:
```bash
mkfs.fat -F32 /dev/nvme0n1p1
mkswap /dev/nvme0n1p2
swapon /dev/nvme0n1p2
mkfs.btrfs -L Arch /dev/nvme0n1p3
mount /dev/nvme0n1p3 /mnt
btrfs subvolume create /mnt/@
btrfs subvolume create /mnt/@home
umount /mnt
mount -o subvol=@,compress=zstd:3,ssd,discard=async /dev/nvme0n1p3 /mnt
mkdir -p /mnt/home /mnt/boot/efi
mount -o subvol=@home,compress=zstd:3,ssd,discard=async /dev/nvme0n1p3 /mnt/home
mount /dev/nvme0n1p1 /mnt/boot/efi
pacstrap -K /mnt base linux linux-firmware btrfs-progs grub efibootmgr sudo vim openssh iwd intel-ucode
genfstab -U /mnt > /mnt/etc/fstab
arch-chroot /mnt
```
### 20.2 chroot 内
```bash
ln -sf /usr/share/zoneinfo/Asia/Shanghai /etc/localtime
hwclock --systohc
sed -i 's/^#en_US.UTF-8 UTF-8/en_US.UTF-8 UTF-8/' /etc/locale.gen
sed -i 's/^#zh_CN.UTF-8 UTF-8/zh_CN.UTF-8 UTF-8/' /etc/locale.gen
locale-gen
echo 'LANG=zh_CN.UTF-8' > /etc/locale.conf
echo 'MyArch' > /etc/hostname
cat > /etc/hosts <<'EOF'
127.0.0.1 localhost
::1 localhost
127.0.1.1 MyArch.localdomain MyArch
EOF
passwd
useradd -m -G wheel -s /usr/bin/bash archuser
passwd archuser
sed -i 's/^# %wheel ALL=(ALL:ALL) ALL/%wheel ALL=(ALL:ALL) ALL/' /etc/sudoers
pacman -S iwd
systemctl enable iwd
systemctl enable systemd-networkd
systemctl enable systemd-resolved
systemctl enable sshd
rm -f /etc/resolv.conf
ln -s /run/systemd/resolve/stub-resolv.conf /etc/resolv.conf
mkinitcpio -P
grub-install --target=x86_64-efi --efi-directory=/boot/efi --bootloader-id=MyArch --recheck
grub-install --target=x86_64-efi --efi-directory=/boot/efi --removable --no-nvram --recheck
grub-mkconfig -o /boot/grub/grub.cfg
grub-script-check /boot/grub/grub.cfg
ssh-keygen -A
exit
```
### 20.3 重启前
```bash
findmnt -R /mnt
cat /mnt/etc/fstab
ls -lh /mnt/boot/vmlinuz-linux /mnt/boot/intel-ucode.img /mnt/boot/initramfs-linux.img
ls -lh /mnt/boot/efi/EFI/MyArch/grubx64.efi /mnt/boot/efi/EFI/Boot/bootx64.efi
efibootmgr -v
```
### 20.4 重启
```bash
umount -R /mnt
swapoff -a
reboot
```
---
## 21. 这次真实安装给出的最终建议
如果你想减少踩坑,我的建议很明确:
### 21.1 如果你用 `/boot/efi`,优先选 GRUB
原因不是"GRUB 更高级",而是它和这种布局天然更契合。
### 21.2 如果你想用 `systemd-boot`,那就先把路径逻辑想清楚
至少得满足下面之一:
- ESP 挂 `/boot`
- 内核和 initramfs 真放在 ESP 上
- 或者你用 UKI
否则你会重现这次的故障。
### 21.3 远程安装的重点不是"装完",而是"重启后还能连回来"
所以要额外保证:
- 网络配置已经持久化
- Wi-Fi profile 已持久化
- SSH host keys 已生成
- SSH 服务已启用
- 最好有一个普通用户可 SSH + `sudo`
### 21.4 重启前一定做静态验收
不要相信"我感觉差不多了"。
真正应该相信的是:
- `findmnt`
- `fstab`
- `ls /boot`
- `ls /boot/efi/EFI/...`
- `efibootmgr -v`
- `grub-script-check`
### 21.5 日志里的所有 warning 不等于引导失败
像这次的:
- `nouveau` GSP 报错
- ACPI 警告
- ESP dirty-bit 警告
都不是这次启动链路真正的致命点。
要先抓住主因,不要被噪音带偏。
---
## 22. 后续建议
这次系统已经成功启动,但如果你继续打磨,建议后面再做这些事:
### 22.1 处理 NVIDIA 驱动
如果你这台机器有 NVIDIA 独显,建议后续安装合适的官方驱动,而不是长期用 `nouveau`。
### 22.2 决定是否允许 root SSH
默认更安全的做法是:
- `root` 只本地登录
- 远程用普通用户 + `sudo`
如果你明确要开 root SSH,再改:
```bash
sudo vim /etc/ssh/sshd_config
sudo systemctl restart sshd
```
但一定知道这是安全面更大的选择。
### 22.3 维护窗口里修 ESP 的 FAT 警告
```bash
sudo fsck.vfat -a /dev/nvme0n1p1
```
### 22.4 补充你自己的子卷策略
比如:
- `@snapshots`
- `@var_log`
- `@pkg`
但那是进阶设计,不是"先把系统装起来"的前提。
---
## 23. 最后的经验总结
这次最核心的经验,不是某条命令,而是一套判断方法:
1. 先判断启动模式,而不是先装引导
2. 先确认挂载结构,而不是先 chroot
3. 先确认路径闭环,而不是只看文件有没有
4. 先做静态验证,再决定重启
5. 远程安装时,把"网络能不能回来"当成引导问题的一部分
如果把这五点记住,你安装 Arch Linux 的成功率会高很多。
---
## 24. 附:这次真实故障的一句话复盘
一句话概括这次真实问题:
> 系统不是没装好,而是 ESP 挂在 `/boot/efi`、内核在根文件系统 `/boot`,但原有 `systemd-boot` 条目却按"内核在 ESP 上"的逻辑写,导致引导路径断裂;改为和挂载结构一致的 GRUB 后,系统成功启动。
这句话如果你能彻底理解,UEFI 下很多"怎么都起不来"的问题你都会看得更清楚。