banner
约 1,800 字
6 分钟

Arch Linux 重装记录

-
-
无标签

摘要

又双叒叕重装了一次系统,这次彻底记下来。NVMe 寿命到头换硬盘,选了 Arch Linux + Btrfs 方案,详细记录分区、安装、配置全过程。

上周三晚上备份 dotfiles 的时候,btrfs scrub 报了一堆 csum error。开始以为是文件系统问题,smartctl -a /dev/nvme0 跑了一下——Media and Data Integrity Errors: 0x0004,NVMe 寿命快到头了。

这台机器是 2022 年初装的 Intel 660p,4 年下来健康度掉到 73%。也该换了。换硬盘是个由头,正好把半年没滚的系统、装到一半的配置、散乱的 dotfiles 全部整一遍。

为什么又选 Arch

这个问题每次都有人问。简短回答:

  • 滚动升级,避免大版本升级的痛苦(Ubuntu 22.04 → 24.04 那种我已经受够了)

  • AUR,几乎所有小众软件都有,不用自己打 deb/rpm

  • Wiki 是最好的 Linux 文档,没有之一

  • 精简,装出来是什么就是什么,没有预装 30 个我用不到的 snap

缺点也有:偶尔滚挂了自己修;systemd 升级偶尔 breaking change。但对我来说收益大于成本。

硬件

  • CPU: AMD Ryzen 5 5600X

  • 主板: B550M Mortar

  • 内存: 32 GB DDR4-3600

  • 新硬盘: WD SN770 1TB(之前是 660p 1TB)

  • 老硬盘(保留为数据盘): Samsung 870 EVO 2TB

  • 显卡: GTX 1660 Super(不玩游戏,但偶尔跑点 CUDA 验证)

分区方案

这次坚持 Btrfs,subvolume 切分。理由:

  1. snapshot 真的能救命(snapper 自动 timeline)

  2. 压缩透明(zstd:3 几乎无感知,节约 20%+ 空间)

  3. subvolume 可以独立挂载,恢复数据方便

bash
# 这次没用 LVM,直接 Btrfs subvolume
# 设备: /dev/nvme0n1

# EFI 分区
fdisk /dev/nvme0n1
# n → p → 1 → 2048 → +512M  (EFI)
# n → p → 2 → 继续         (Btrfs)
# t → 1 → uefi
# t → 2 → linux filesystem

mkfs.fat -F32 /dev/nvme0n1p1
mkfs.btrfs -f /dev/nvme0n1p2
mount /dev/nvme0n1p2 /mnt

# subvolume 切分
btrfs subvolume create /mnt/@
btrfs subvolume create /mnt/@home
btrfs subvolume create /mnt/@var-log
btrfs subvolume create /mnt/@var-cache
btrfs subvolume create /mnt/@snapshots

# 卸载重挂,每个 subvolume 单独挂载
umount /mnt
mount -o subvol=@,compress=zstd:3,noatime /dev/nvme0n1p2 /mnt
mkdir -p /mnt/{home,var/log,var/cache,.snapshots}
mount -o subvol=@home,compress=zstd:3,noatime /dev/nvme0n1p2 /mnt/home
mount -o subvol=@var-log,compress=zstd:3,noatime /dev/nvme0n1p2 /mnt/var/log
mount -o subvol=@var-cache,compress=zstd:3,noatime /dev/nvme0n1p2 /mnt/var/cache
mount -o subvol=@snapshots,compress=zstd:3,noatime /dev/nvme0n1p2 /mnt/.snapshots
mount /dev/nvme0n1p1 /mnt/boot/efi

坑 1: 一定要在装系统前就建好所有 subvolume 并挂载,之后再调整会很麻烦。我第一遍手抖漏了 @var-log,导致 pacman 装日志写到了 @,重做了一遍。

坑 2: @snapshots 不要放在 @ 下面,否则 snapper 创建 snapshot 时会把当前 @ 里的内容也卷进去。独立 top-level 是正解。

安装基础系统

bash
# 装包(精简,只装后续会用的)
pacstrap -K /mnt \
    base linux linux-firmware \
    linux-headers \
    btrfs-progs \
    intel-ucode \
    networkmanager \
    vim \
    git \
    sudo \
    base-devel \
    reflector \
    snapper \
    snap-pac

# fstab
genfstab -U /mnt >> /mnt/etc/fstab

# 验证 fstab
cat /mnt/etc/fstab
# 看到 UUID 不是 /dev/nvme0n1pX 这样的设备名,就对了

chroot 进去之后:

bash
arch-chroot /mnt

# 时区
ln -sf /usr/share/zoneinfo/Asia/Shanghai /etc/localtime
hwclock --systohc

# locale
sed -i 's/^#en_US.UTF-8/en_US.UTF-8/' /etc/locale.gen
sed -i 's/^#zh_CN.UTF-8/zh_CN.UTF-8/' /etc/locale.gen
locale-gen
echo "LANG=en_US.UTF-8" > /etc/locale.conf
echo "KEYMAP=us" > /etc/vconsole.conf

# hostname
echo "kvasir" > /etc/hostname

# hosts
cat > /etc/hosts <<EOF
127.0.0.1   localhost
::1         localhost
127.0.1.1   kvasir.localdomain kvasir
EOF

# root 密码
passwd

# 新用户
useradd -m -G wheel,audio,video,storage,power stun
passwd stun
EDITOR=vim visudo  # 取消 %wheel ALL=(ALL) ALL 的注释

引导

systemd-boot(简洁,不用装 grub)。

bash
bootctl install

# 自动生成的 entry 在 /boot/loader/entries/
# 这次用 uki,统一管理内核参数
pacman -S --needed linux linux-headers
# linux 6.10+ 默认开 UKI 支持

# /boot/loader/loader.conf
cat > /boot/loader/loader.conf <<EOF
default arch
timeout 3
console-mode max
editor no
EOF

# 自动 entry
bootctl update

网络

bash
systemctl enable --now NetworkManager

# 用 nmcli 配 wifi
nmcli device wifi list
nmcli device wifi connect "MySSID" password "..."

# 或者用 iwd(更轻)
pacman -S iwd
systemctl disable --now wpa_supplicant
systemctl enable --now iwd

我两台机器一台用 NM,一台用 iwd。看场景,桌面选 NM(GUI 友好),服务器选 iwd。

桌面环境:KDE Plasma

用了 4 年 GNOME,这次换 KDE。原因是:

  • GNOME 的扩展 API 改得太勤,每次大版本都要重写我的几个扩展

  • KDE 的窗口管理逻辑更接近传统桌面,多屏行为可预测

  • Wayland 支持终于稳定了(KDE Plasma 6)

bash
pacman -S plasma-desktop sddm
systemctl enable --now sddm

# Wayland session 默认开启
# /etc/sddm.conf.d/wayland.conf
cat > /etc/sddm.conf.d/wayland.conf <<EOF
[General]
DisplayServer=wayland
EOF

# 重启登录
reboot

Snapper 配置(这次才搞对)

前几次装都跳过了 snapper,结果某次 pacman 滚挂恢复起来要手动 mkinitcpio,惨。这次老老实实配了:

bash
# snapper 配置 root subvolume
snapper -c root create-config /
# 这一步会创建 /etc/snapper/configs/root 和 .snapshots 目录

# 但因为我们用的 top-level @snapshots 而不是 /.snapshots,
# 需要调整一下 fstab
umount /.snapshots
rmdir /.snapshots
mkdir -p /.snapshots
mount -o subvol=@snapshots,compress=zstd:3 /dev/nvme0n1p2 /.snapshots
# 把这行加到 /etc/fstab
# 取得 UUID
blkid /dev/nvme0n1p2

# 自动 timeline
systemctl enable --now snapper-timeline.timer
# 自动清理
systemctl enable --now snapper-cleanup.timer

# pre/post 包安装自动 snapshot(snap-pac 已在 pacstrap 时装上)
# 装个包试试
pacman -S htop
snapper list
# Type | Pre # | Date | User | Cleanup | Description
# -----+-------+------+------+---------+-----------
# pre  |       |      |      |         | pre  pacman -Syu htop
# post |     1 | ...  | root |         | post pacman -Syu htop

恢复数据

老硬盘 870 EVO 没动,挂上来直接挂载:

bash
# 找到设备
lsblk

# 挂载到 /mnt/old
mkdir -p /mnt/old
mount -o ro /dev/sda1 /mnt/old
# 如果是 luks
cryptsetup open /dev/sda1 old-data
mount -o ro /dev/mapper/old-data /mnt/old

# 拷贝需要的(用 rsync 保留属性)
rsync -aAXv /mnt/old/home/stun/Pictures/ /home/stun/Pictures/
rsync -aAXv /mnt/old/home/stun/Documents/ /home/stun/Documents/
# ... 等等

坑: 一定要 -A(保留 ACL)和 -X(保留扩展属性),否则拷贝过来的文件权限会乱。

备份策略(这次整理成清单)

  • /etcetckeeper 进 git,每天自动 commit

  • dotfiles → chezmoi,跨机器同步

  • 重要文档(/Documents、/Pictures)→ syncthing 到 NAS + 加密备份到 Backblaze B2

  • 系统 snapshot → snapper + btrfs(timeline + pre/post pacman)

  • 密码 → pass + git 私有 repo 同步

装完包清单(备忘)

bash
# 系统管理
pacman -S htop btop nvtop duf dust procs ripgrep fd fzf zoxide

# 开发
pacman -S base-devel git github-cli neovim tmux zsh jq yq

# 网络
pacman -S openssh rsync syncthing wireguard-tools

# 媒体
pacman -S mpv ffmpeg imagemagick

# 文档
pacman -S zathura zathura-pdf-mupdf pandoc

# AUR
git clone https://aur.archlinux.org/yay.git
cd yay && makepkg -si
yay -S visual-studio-code-bin google-chrome 1password

结语

装完系统本身就 1 小时不到,剩下 3 小时全在调教 dotfiles、配置 snapper、配 syncthing、迁移密码库。这些"装完之后"的工作才是真正的痛点。

下次再装,估计 2027 年。希望届时我已经把整套流程写成 ansible playbook 了,而不是又手敲一遍

END

相关文章

暂无相关文章