如何优雅地重新安装你的Arch Linux
日常使用
- 有序存放工作生活中使用的文件,并使用
rsync
等工具备份防止丢失 - 妥善配置系统,并使用脚本管理所有配置文件
- 对自己安装过的软件心中有数
在旧系统上备份
用脚本备份包和配置文件
下面的脚本作为参考
#/bin/bash
# update : a script to backup and restore my work environment on ArchLinux
## Please run this script as wheel user after basic install of Arch Linux.
# Principles
## 1. Take detailed notes in the script file
## 2. Always only do somesthing after judging that it has not been done yet.
## 3. exit if somesthing goes wrong.
set -e
## Config
bak_path="$HOME/all/local/share/backup-config"
# Backup or Recover?
case $1 in
backup)
option=""
;;
recover)
option="r"
;;
*)
echo "Please use option 'backup or 'recover'."
exit 1
;;
esac
# Func
has_installed(){
pacman -Qs | grep -E "^local/${1} " &> /dev/null
}
update_pkg(){
if [[ -n $option ]]; then
local pkg
for pkg in "$@"; do
has_installed "$pkg" || sudo pacman -S --noconfirm "$pkg"
done
fi
}
update_aur_pkg(){
if [[ -n $option ]]; then
local pkg
for pkg in "$@"; do
has_installed "$pkg" || yay -S --noconfirm "$pkg"
done
fi
}
update_config(){
local config_file
local config_basename
local relative_dir
for config_file in "$@"; do
config_basename=$(basename "$config_file")
if [[ "$config_file" == ~/* ]]; then
# wheel-home
relative_dir=$(dirname "${config_file/#$HOME/}")
if [[ -n $option ]]; then
# recover
mkdir -p ~/$relative_dir
rsync -rlpt $bak_path/wheel-home/$relative_dir/$config_basename ~/$relative_dir
else
# backup
mkdir -p $bak_path/wheel-home/$relative_dir
rsync -rlpt --delete "$config_file" $bak_path/wheel-home/$relative_dir/
fi
else
# fs-root
relative_dir=$(dirname "$config_file")
if [[ -n $option ]]; then
# recover
sudo mkdir -p $relative_dir
sudo rsync -a --no-D $bak_path/fs-root/$relative_dir/$config_basename $relative_dir
sudo chown -R root:root "$config_file"
else
# backup
sudo mkdir -p $bak_path/fs-root/$relative_dir
sudo rsync -a --no-D --delete "$config_file" $bak_path/fs-root/$relative_dir/
fi
fi
done
}
# main
if id -nG "$USER" | grep -qw "wheel"; then
# grub
update_config /etc/default/grub
[[ -n $option ]] && sudo grub-mkconfig -o /boot/grub/grub.cfg
# Internet Connection
## DNS
[[ -n $option ]] && sudo chattr -i /etc/resolv.conf
update_config /etc/resolv.conf
[[ -n $option ]] && sudo chattr +i /etc/resolv.conf
## wpa
update_config /etc/wpa_supplicant
wifi_interface=$(ip link show | awk -F: '/wl/ {print $2}' | tr -d ' ')
if [[ -n $option ]]; then
sudo mkdir -p "/etc/systemd/system/"
sudo rm -f /etc/systemd/system/wpa_supplicant*
sudo cp ${bak_path}/fs-root/etc/systemd/system/wpa_supplicant@*.service "/etc/systemd/system/wpa_supplicant@${wifi_interface}.service"
sudo systemctl enable --now "wpa_supplicant@${wifi_interface}.service"
else
sudo mkdir -p "${bak_path}/fs-root/etc/systemd/system/"
sudo rm -f ${bak_path}/fs-root/etc/systemd/system/wpa_supplicant*
sudo cp "/etc/systemd/system/wpa_supplicant@${wifi_interface}.service" "${bak_path}/fs-root/etc/systemd/system/"
fi
## dhcpcd
[[ -n $option ]] && sudo systemctl enable --now dhcpcd
echo "[Done] Internet Connection"
# Time
## time zone
[[ -n $option ]] && sudo ln -sf /usr/share/zoneinfo/Asia/Shanghai /etc/localtime
## RTC time
[[ -n $option ]] && sudo timedatectl set-ntp on
[[ -n $option ]] && sudo timedatectl set-local-rtc 0
## write to device time
[[ -n $option ]] && sudo hwclock --systohc
echo "[Done] Time"
# Pacman, AUR, git, pip
update_config /etc/pacman.conf
update_config /etc/pacman.d/mirrorlist
update_config /etc/pacman.d/hooks/update_snapshot.hook
[[ -n $option ]] && sudo pacman -Syu --noconfirm
update_pkg git git-lfs openssh
update_config ~/.gitconfig
update_config ~/.ssh # ssh for github
[[ -n $option ]] && git lfs install
update_config ~/.pip/pip.conf
## yay, see: https://wiki.archlinuxcn.org/wiki/Yay
if [[ -n $option ]] && ! has_installed "yay-bin" ; then
cd ~/local/lib/yay-bin/
git pull origin master
makepkg -si --noconfirm
fi
echo "[Done] Pacman, AUR, Git, Pip"
# language & Font
## lang
update_config /etc/locale.gen
[[ -n $option ]] && sudo locale-gen
update_config /etc/locale.conf
## font
update_pkg wqy-microhei noto-fonts-cjk noto-fonts-emoji noto-fonts-extra
update_config /etc/fonts/conf.d/64-language-selector-prefer.conf
echo "[Done] Font"
# dir
update_config ~/.config/user-dirs.conf
update_config ~/.config/user-dirs.dirs
echo "[Done] Dir"
# Shell
## bash
update_pkg bash-completion fzf powerline powerline-fonts
update_config ~/.bash
update_config ~/.bash_profile
update_config ~/.bashrc
## nvim
update_pkg neovim
update_pkg ccls jedi-language-server rust-analyzer texlab # language servers
update_aur_pkg cmake-language-server fortls
update_config ~/.config/nvim # Please wait at first start
......
# develop
update_pkg jdk17-openjdk jdk21-openjdk # java for minecraft
update_pkg rust
update_pkg gdb
update_pkg inetutils # MATHEMATICA requires
[[ -n $option ]] && sudo systemctl enable --now avahi-daemon.service # for MATHEMATICA
echo "[Done] develop"
# reboot
[[ -n $option ]] && echo "Alright. Please reboot..."
else
echo "Please run this script as user in wheel group"
exit 1
fi
echo "OK"
备份所有必要文件到备用硬盘
我所有有用的文件储存在~/all/
目录下,并通过自己写的一个名叫poshd的bash脚本管理。
像这样备份all/
到/mnt/
:
po -b /mnt
新系统的基础安装
参考之前的文章
用live系统启动
制作USB闪存安装介质
archlinux-2024.06.01-x86_64.iso 01-Jun-2024 17:09 1168146432
archlinux-2024.06.01-x86_64.iso.sig 01-Jun-2024 17:09 141
前者是我们需要的ISO,后者是ISO的发布者使用私钥生成的签名文件,可以用来验证原文件是否完整且完全没有被修改。像这样进行验证:
# On Arch linux (-v = --verify)
pacman-key -v archlinux-version-x86_64.iso.sig
# On any system with GnuPG installed
gpg --keyserver-options auto-key-retrieve --verify archlinux-version-x86_64.iso.sig
看到"Good signature"之类的字眼,说明验证成功。
- 插入自己的闪存,然后以root身份使用
dd
命令写入ISO,注意of参数需要的是磁盘设备名而不是分区名 (甚至可以使用cat或cp)
dd bs=4M if=path/to/archlinux-version-x86_64.iso of=/dev/disk/by-id/usb-My_flash_drive conv=fsync oflag=direct status=progress
下面解释一下这行命令
bs=4M
这个参数指定了块大小(block size)为4MB, 使用较大的块理论上能提高复制的效率,但复制效率的上限被诸多因素定死,设置为4M即可。conv=fsync
这个选项确保在复制过程中数据写入到磁盘时,所有的内存缓冲区都被刷新(fsync),以保证数据的完整性oflag=direct
这个选项告诉dd
直接写入到输出文件,绕过系统缓存。这样可以提高大文件写入时的性能,并减少系统缓存对其他进程的影响。status=progress
这个选项告诉dd
输出进度信息,使用户可以看到复制过程中的进度。
通过自己的闪存启动live系统
配置镜像源
把live系统上预装的这个没点用的工具停用了
systemctl stop reflector.service
打开/etc/pacman.d/mirrorlist
, 把下面四行放在最前面:
Server = http://mirrors.ustc.edu.cn/archlinux/$repo/os/$arch
Server = https://mirrors.ustc.edu.cn/archlinux/$repo/os/$arch
Server = http://mirrors.tuna.tsinghua.edu.cn/archlinux/$repo/os/$arch
Server = https://mirrors.tuna.tsinghua.edu.cn/archlinux/$repo/os/$arch
连接网络,同步时间
- 连接网络。有线网络直接插上网线即可,无线网络可以用
iwctl
或wpa_suppliant + wpa_cli
。 - 更新时钟 在网络传输的各种较验中,时钟错误可能导致失败。使用以下命令更新live系统的时钟
timedatectl set-ntp true #将系统时间与网络时间进行同步
timedatectl status #检查服务状态
分区,文件系统和挂载; 生成fstab
- 分区方案:
- Disk1
/boot
(ESP): 1G- SWAP: 20G (slightly larger than physical memory)
/
: remain space
- Disk2
/home
(不需要用fdisk进行分区)
- 创建文件系统
mkfs.fat -F 32 /dev/efi_system_partition # ESP
mkswap /dev/hdb1 # SWAP
mkfs.btrfs -L mylabel /dev/partition # /
mkfs.xfs device # /home
- 挂载和创建Btrfs子卷
mount /dev/partition_root /mnt
btrfs subvolume create /mnt/@current
mount -m /dev/partition_efi /mnt/@current/boot
mount -m /dev/partition_home /mnt/@current/home
- 生成fstab
- 为了在启动我们安装的系统时能够自动挂载,需要生成fstab文件
mkdir /mnt/@current/etc
# 一定要用-U,即根据UUID挂载,否则默认根据盘名挂载,这在有多个硬盘时会因为顺序不定而出现问题。
genfstab -U /mnt/@current >> /mnt/@current/etc/fstab
- 向fstab文件中追加一行swap分区
首先以root身份使用
blkid
命令查看UUID
(也可用lsblk)
lsblk -o NAME,FSTYPE,UUID
然后用cat等工具在fstab文件末尾追加以下文本, 其中discard选项是启用丢弃策略,即swapon -d
。
# <file system> <mount point> <type> <options> <dump> <pass>
UUID=your_swap_uuid none swap defaults,discard 0 0
- 检查没有错误
cat /mnt/@current/etc/fstab
向新系统安装基本包
- 最基本的包
pacstrap /mnt/@current base base-devel linux-zen linux-zen-headers linux-firmware
base
: Arch Linux的基础包集合,包含了一个最小化的可用系统所需的核心软件包。它包括基本的文件系统工具、基本的 Shell(如bash)、核心库和其他基本工具。base-devel
: 包含了一组用于开发的软件包, 包括编译器、调试工具等。安装它是为了方便安装和编译其他软件包linux-zen
: zen内核, 相比默认内核桌面使用体验更佳。linux-zen-headers
: 与linux-zen
包对应的内核头文件包, 它包含了用于编译内核模块和驱动程序的头文件。linux-firmware
: 各种硬件设备所需的固件文件
- 系统引导和正常运行必须的包
- 安装微码
pacstrap /mnt/@current intel-ucode #Intel
pacstrap /mnt/@current amd-ucode #AMD
- 安装引导程序
pacstrap /mnt/@current grub efibootmgr
- 安装文件系统工具
pascstrap /mnt/@current btrfs-progs xfsprogs
- 安装联网工具, 备份恢复工具, 编辑器
pascstrap /mnt/@current wpa_suppliant dhcpcd rsync neovim
Chroot
arch-chroot /mnt/@current
新系统的引导
安装GRUB引导加载程序到/boot
grub-install --target=x86_64-efi --efi-directory=/boot --bootloader-id=GRUB
确认/etc/default/grub
中这一行为:
GRUB_CMDLINE_LINUX="rootflags=subvol=/@current"
最后生成GRUB所需的配置文件
grub-mkconfig -o /boot/grub/grub.cfg
设置主机名
nvim /etc/hostname
在这个文件中输入你想好的主机名即可,然后
nvim /etc/hosts
在这个文件下加入类似以下内容:
127.0.0.1 localhost
::1 localhost
127.0.1.1 my_hostname
root用户
给root用户添加密码
passwd root
添加一个wheel用户
# -m同时创建家目录,wheel是可sudo的用户组
useradd -m -G wheel -s /bin/bash user0
# 设置密码
passwd user0
sudo的配置
sudo在archlinux中属于基本组件,用来暂时暂时以其它用户的身份运行代码或执行文件。
sudo用户的配置文件是/etc/sudoers
, 这个文件原则上只能通过visudo
命令编辑
# 用环境变量指明编辑器是vim, 以后安装了neovim也可指定为nvim.
EDITOR=vim visudo
这个文件中我们只需要关注以下部分
##
## User privilege specification
##
root ALL=(ALL:ALL) ALL
## Uncomment to allow members of group wheel to execute any command
# %wheel ALL=(ALL:ALL) ALL
## Same thing without a password
%wheel ALL=(ALL:ALL) NOPASSWD: ALL
## Uncomment to allow members of group sudo to execute any command
# %sudo ALL=(ALL:ALL) ALL
## Uncomment to allow any user to run sudo if they know the password
## of the user they are running the command as (root by default).
# Defaults targetpw # Ask for the password of the target user
# ALL ALL=(ALL:ALL) ALL # WARNING: only use this together with 'Defaults targetpw'
下面以root ALL=(ALL:ALL) ALL
为例讲解一下这几行命令
- 开头的
root
表示要操作的用户,这里是root用户 - 第1个ALL所在的字段表示主机名,这里用"ALL"说明指定的用户在任何主机上都能使用
sudo
命令 ()
中的两个字段,第1个ALL表示可以以任何用户身份运行命令;第二个ALL表示可以以任何组身份运行命令。- 最后一个ALL表示允许执行所有命令
卸载和重启
exit # 退回安装环境#
umount -R /mnt # 卸载新分区
reboot # 重启
拔掉闪存,启动新系统
新系统上恢复到旧系统工作环境
恢复工作文件
挂载备份盘后,用po进行恢复
. /mnt/all/local/lib/bash/bash_tools/poshd/po.sh
po -r /mnt
恢复配置文件和软件包
使用前文的update脚本进行恢复
./update.sh recover