0%

自由王国-没有银弹

一、总论

这是一篇记录我配置新电脑,在新电脑上配置系统的过程。

之所以取名叫作“没有银弹”,是因为我被挑选硬件、软件的过程折磨的精疲力竭。“没有银弹”虽然是一个老生常谈的话题,但是发现它出现在非软件工程领域,还是非常让人意外的。

没有一个笔记本、可以兼具 PC 的量大管饱和 Macbook 的高续航和漂亮屏幕;没有一个操作系统,可以兼具 Linux 的开发环境相似性、Windows 的普世和 MacOS 的闭合生态;没有一个发行版,可以兼具 ArchLinux 的高可控性和及时性,NixOS 的可复现性,Ubuntu 的稳定性;没有一个图形服务器兼具 Xorg 的适配性和 Wayland 的高性能;甚至没有一个编辑器,可以兼具 Emacs 的键盘操作和 VSCode 的 Remote 功能!

在我各种权衡利弊下,我得到了一个低续航、很沉、没有独显、甚至还不便宜的笔记本;上面装着的操作系统,无法驱动触摸板、声卡和蓝牙;软件包管理形式依然是 pacman,只要我开始更新,我就要一直更新;依然是老旧的 Xorg,每使用一天就是在向死亡奔赴一天;都 2025 了,我甚至还要被 Emacs 的沉没成本绑架以至于无法使用 VSCode。

这岂止是“没有银弹”,这完全是“无法胜利”!我只能忍受这些事情,关键是我都不知道我为什么要忍受这些。我想起了我第一次看见学长在 Manjaro 的 Konsole 上敲命令的样子;我想起了同学开着 VSCode 打开 WSL 的样子;我想起了师兄一只手端着 Mac 去找老师讨论的样子。是的,我羡慕他们。但是又不止是这些,我想到我作为一个 system 方向的研究生,我连我自己的 Operating System 都无法控制;我想到了我第一次编译 Linux 内核的时候,哗哗滚动的命令行;我想到了我的 Emacs 可以显示出来文件图标的样子。

所以到底为什么?我为什么要执着于这些事情?我在执着于我自己。如果我放弃这些东西,我还是我自己吗?我管计算机世界叫作“自由王国”,因为我相信只要愿意付出精力和时间,那么就会获得自由。可是这些事情告诉我,不是这样的。我无法胜利,我无法自由,在我剩余的生命中,只有一次又一次的妥协。无数次妥协、无数次失败的我,还有自由意志可言吗?而失去自由意志的我,还是我吗?

如果,“没有银弹”这个事情,不止在“软件工程”和“装新电脑”这两件事情上发生呢?或许在爱情、事业、家庭中,它们都在发生。。。我到底在执着什么呢?

我想用我的余生回答这个问题。


二、Why Not?

这里会记录我为什么不做一些选择。

2.1 Wayland

目前 wayland 不支持腾讯会议的屏幕共享功能,这导致它没有办法作为一个办公本出现。此外 wayland 也不支持类似于 peek 这样的屏幕录制 gif 工具,我也很需要这种工具。

2.2 Other OS

2.2.1 NixOS

本次装机因为机子太新了,所以 NixOS 的网卡驱动一直装不上去。

此外 NixOS 除了可复现性以外,它还提供了一套声明式配置的设计理念。虽然声明式可以有效避免配置项本身的变化,但是我觉得用 Linux,不就是为了用它命令式“刀耕火种“、”手搓系统“的爽感嘛?如果啥啥都要去查 NixOS 的配置文档,那又有什么意思呢?

2.2.2 Ubuntu

太旧了,软件更新实在是太不及时了,我不想用一个 26 版本的 Emacs。

2.3 KDE

我想要版本监控我的 DE 配置,但是 KDE 的配置文件近乎二进制,很难监控。

2.4 14 Inch

没啥,我一个 186 的壮汉,岂能拿这种小家子气的机子。


三、Setup

3.1 制作装机盘

在这个页面下载 ArchLinux ISO 镜像文件,并使用 dd 命令制作装机盘:

sudo dd bs=4M if=/path/to/archlinux.iso of=/dev/sdx status=progress oflag=sync

其中 status 用于显示 dd 进程,oflay 用于确保写入同步。

3.2 Live 环境

Live 环境指的是采用 U 盘引导进入的系统,当我们把系统安装到主机上,这个过程就结束了(就可以拔 U 盘了)。

3.2.1 分区前

reflector 会为你选择速度合适的镜像源,但其结果并不准确,同时会清空配置文件中的内容,对于新人来讲并不适用,我们首先对其进行禁用。

systemctl stop reflector.service

无线连接使用 iwctl 命令进行,按照如下步骤进行网络连接:

iwctl                           # 执行 iwctl 命令,进入交互式命令行
device list                     # 列出设备名,比如无线网卡看到叫 wlan0
station wlan0 scan              # 扫描网络
station wlan0 get-networks      #列出网络 比如想连接 YOUR-WIRELESS-NAME 这个无线
station wlan0 connect YOUR-WIRELESS-NAME # 进行连接 输入密码即可
exit                            # 成功后 exit 退出

可以等待几秒等网络建立链接后再进行下面测试网络的操作。

ping www.gnu.org

如果不能正常使用网络,那么要确定网卡是否 up

ip link
ip link set wlan0 up

如果还不行,其实可以将手机和电脑连接在一起,在手机中选择“共享网络”给电脑。

更新系统时钟:

timedatectl set-ntp true    # 将系统时间与网络时间进行同步
timedatectl status          # 检查服务状态

主要是查看 System clock synchronizedNTP Service 这两项,时区设置在后面。

3.2.2 分区

为了使得 OS 能够安装在硬盘上并正常启动,我们需要对硬盘进行分区。我们可以先使用如下命令查看一下块设备情况:

lsblk

对于 laptop 来说,一般是有 sda 对应 U 盘,nvme0n1 对应硬盘。我们要对 nvme0n1 进行分区:

  • boot 分区:也就是 UEFI 启动时需要的分区,需要 FAT32 格式。
  • swap 分区:当物理内存溢出时,可以交换到硬盘上的这个分区。此外休眠(Hibernate)时的状态文件也会保存在这个分区。
  • / 分区:主分区
  • /home 分区:家目录分区

其实没有 swap 分区也可以,目前 laptop 的大内存一般也不会出现溢出的情况。即使需要 Hibernate 的功能,也可以用 swapfile 机制代替。但是我觉得 swapfile 太丑了,而且据说性能不如 swap 分区好,我就选择了 swap 分区。

此外还有要不要对 /home 单独分区的问题。对 /home 单独分区,可以隔绝系统软件和用户目录对彼此的影响,还可以方便地更换发行版。我之前出现过一次差点重装系统的事故,如果对 /home 单独分区,可以在重装系统的时候避免损坏家目录中的数据文件。

在进行分区前,需要创建 GPT 分区表:

lsblk                       # 显示分区情况 找到你想安装的磁盘名称
parted /dev/nvme0n1         # 执行 parted ,进入交互式命令行,进行磁盘类型变更
(parted) mktable            # 输入 mktable
New disk label type? gpt    # 输入 gpt 将磁盘类型转换为 gpt 如磁盘有数据会警告,输入 yes 即可
quit                        # 最后 quit 退出 parted 命令行交互

然后执行如下命令进入 TUI 界面对硬盘进行分区:

cfdisk /dev/nvme0n1

界面非常简单,用方向键和回车就可以操作,分区的具体信息如下表所示:

Partition Size Type
boot 512 MiB EFI System
swap 16 GiB Linux Swap
/ 144 GiB Linux filesystem
/home 793.4 GiB Linux filesystem

GB 是以 10 为基数的,厂商宣传一般用这个,而 GiB 是以 2 为基数的,更适合 SSD 硬件体质。

关于 / 的大小,我使用了 5 年的笔记本大约是 120G,其中有 50G 的 cache 还没有清理,所以我觉得 144G 是一个比较合理的数值。而关于 swap 分区的大小,纯粹是我舍不得了。

使用如下命令复查分区情况:

fdisk -l

然后格式化分区:

# boot
mkfs.vfat -F 32 /dev/nvme0n1p1
# swap
mkswap /dev/nvme0n1p2
swapon /dev/nvme0n1p2
# root
mkfs.ext4 /dev/nvme0n1p3
mkfs.ext4 /dev/nvme0n1p4

至于为啥选择了 ext4 而没有选择 btrfs,是因为 ext4 性能好,稳定,兼容性好,虽然 btrfs 功能多,但是那些功能我也不懂,所以就没有选。

3.2.3 挂载

要按照顺序对分区进行挂载,先挂载 / 分区:

# root
mount /dev/nvme0n1p3 /mnt
# boot
mkdir /mnt/boot
mount /dev/nvme0n1p1 /mnt/boot
# home
mkdir /mnt/home
mount /dev/nvme0n1p4 /mnt/home

然后修改镜像源,来为安装软件做准备:

vim /etc/pacman.d/mirrorlist

3.2.4 初步安装与配置

本质是把中国的源往前提:

Server = https://mirrors.ustc.edu.cn/archlinux/$repo/os/$arch
Server = https://mirrors.tuna.tsinghua.edu.cn/archlinux/$repo/os/$arch

然后安装基础的包:

pacstrap /mnt base base-devel linux linux-headers linux-firmware  # base-devel 在 AUR 包的安装是必须的

安装必要的功能性软件

pacstrap /mnt dhcpcd iwd vim bash-completion   # 有线所需(iwd 也需要 dhcpcd )、无线所需、编辑器、补全工具

生成 fstab 文件:

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

chroot

arch-chroot /mnt

设置时区:

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

然后设置 locale,它决定了地域、货币、时区日期的格式、字符排列方式和其他本地化标准。先用 vim 去掉 /etc/locale.gen 文件中的 en_US.UTF-8zh_CN.UTF-8 的注释。

vim /etc/locale.gen

然后使用如下命令生成 locale:

locale-gen

最后向 /etc/locale.conf 导入内容

echo 'LANG=en_US.UTF-8'  > /etc/locale.conf

然后在 /etc/hostname 设置主机名:

vim /etc/hostname

接下来在/etc/hosts 设置与其匹配的条目。

vim /etc/hosts

加入如下内容:

127.0.0.1   localhost
::1         localhost
127.0.1.1   loquat

然后为 root 设置密码:

passwd root

然后安装微码:

pacman -S intel-ucode   # Intel
pacman -S amd-ucode     # AMD

3.2.5 GRUB

首先安装引导程序:

# grub 是启动引导器,efibootmgr 被 grub 脚本用来将启动项写入 NVRAM
pacman -S grub efibootmgr
grub-install --target=x86_64-efi --efi-directory=/boot --bootloader-id=GRUB

然后通过编辑 /etc/default/grub 文件,配置 grub 传递给 Linux Kernel 的参数:

GRUB_CMDLINE_LINUX_DEFAULT="loglevel=5 nowatchdog"

增加 log level 有助于 debug, nowatchdog 可以提高启动速度。

然后让 grub 生成配置文件:

grub-mkconfig -o /boot/grub/grub.cfg

3.2.6 完成安装

退出 chroot 环境,重启:

exit                # 退回安装环境#
umount -R  /mnt     # 卸载新分区
reboot              # 重启

重启后启动 dhcp 和无线网络服务

systemctl start dhcpcd
systemctl start iwd

然后就可以使用 iwctl 工具来连接网络了。

3.3 开始之前

在我们开始安装各种应用软件之前,我们还需要做一些准备工作:

3.3.1 创建用户

创建一个普通用户 thysrael:

useradd -m -G wheel -s /bin/bash thysrael  # wheel 附加组可使用 sudo,-m 同时创建用户家目录

设置 thysrael 的密码:

passwd thysreal

编辑 sudoers 配置文件

EDITOR=vim visudo  # 需要以 root 用户运行 visudo 命令

找到下面这样的一行,把前面的注释符号 # 去掉,:wq 保存并退出即可。

#%wheel ALL=(ALL:ALL) ALL

3.3.2 网络连接

我们在 live 环境下使用的网络连接工具是 dhcpcd 配合 iwd,但是在日常使用中,我们更喜欢 networkmanager,因为它的使用更加简便,而且和 GUI 界面融合的更好。所以我们安装 networkmanager 并关闭 dhcpcdiwd 的功能。

sudo pacman -S networkmanager
sudo systemctl disable iwd                             # 确保 iwd 开机处于关闭状态,其无线连接会与 NetworkManager 冲突
sudo systemctl stop iwd                                # 同上,立即关闭 iwd
sudo systemctl enable --now NetworkManager             # 确保先启动 NetworkManager,并进行网络连接

可能需要重启才能生效。

我们可以使用如下命令在 CLI 界面使用 networkmanager:

# 列出所有设备
nmcli device
# 显示所有可用的 Wi-Fi 网络
nmcli device wifi list
# 连接到一个 Wi-Fi 网络
nmcli device wifi connect "SSID_NAME" password "your_password"
# 断开网络连接
nmcli device disconnect iface_name

应该配置一次后就可以自动连接了。

3.3.3 包管理器

首先我们先开启 32 位支持库(我也不知道为啥,可能这样包的数量就变多了吧),编辑 /etc/pacman.conf[multilib] 那一节的注释取消掉。

然后使用如下命令刷新 pacman 数据库:

pacman -Syyu

然后我们要安装 yay ,目前 yay 被墙了,所以我们要先安装 git ,然后 clone 下来 yay 仓库并构建:

pacman -S git
git clone https://aur.archlinux.org/yay-bin.git # 一定得是 yay-bin,因为 yay 基于 go 构建,go 也被墙了
cd yay-bin
makepkg -si

3.4 GUI

我们要安装 i3 作为我们的窗口管理器。

3.4.1 显卡驱动

首先安装 Intel 集成显卡驱动:

pacman -S mesa lib32-mesa vulkan-intel lib32-vulkan-intel
  • mesa 是开源的 OpenGL 实现,支持 Intel 核显的 3D 图形渲染。
  • Vulkan 是核显的 Vulkan API 驱动,支持现代图形渲染技术(如光线追踪、高性能计算)。

不建议安装 xf86-video-intel ,似乎说性能不好。

3.4.2 Xorg

安装 xorg 作为我们的图形服务器:

pacman -S xorg-server

xorg-server :是一个开源的 X Window System 服务器,用于管理图形显示和用户输入。

3.4.3 登录器

我们需要先安装登录器,这样我们一开机就可以进入 GUI 了:

sudo pacman -S sdm
sudo systemctl enable sdm.service

本来想安装 lightdm 的,结果启动不成功。

3.4.4 i3wm

sudo pacman -S i3-wm i3status dmenu
  • i3-wm 是一个高度可定制、平铺式窗口管理器。

  • i3status 是一个简单的状态栏生成器,它可以在 i3-wm 的栏上显示有关系统状态(如时间、电池状态、网络连接等)的信息。

  • dmenu 是一个轻量级的动态菜单。它可以用于启动应用程序、执行命令或选择其他操作。

此外,为了让我们进入 I3 后有个终端模拟器可以用,我们还安装 kitty:

sudo pacman -S kitty

然后我们重启就可以了。

3.5 硬件适配

3.5.1 改键位

然后我们就可以安装我心心念念的改键器了:

pacman -S interception-caps2esc

安装好了以后,在/etc/udevmon.yaml添加下列代码

- JOB: "intercept -g $DEVNODE | caps2esc | uinput -d $DEVNODE"
  DEVICE:
     EVENTS:
       EV_KEY: [KEY_CAPSLOCK, KEY_ESC]

/etc/systemd/system/udevmon.service 中添加下列代码

[Unit]
Description=udevmon
Wants=systemd-udev-settle.service
After=systemd-udev-settle.service

[Service]
ExecStart=/usr/bin/nice -n -20 /usr/bin/udevmon -c /etc/udevmon.yaml

[Install]
WantedBy=multi-user.target

最后使用如下命令来启动:

sudo systemctl enable --now udevmon