时隔多年终于回到技术栏目,第一篇博客竟然又是环境配置(笑)。
这次我们要在实机上安装 Arch Linux 了。实际上这也不是我第一次在实机上装 Arch,但标题中强调的“2021 年”,意味着这次肯定要有与之前不一样的东西。这次安装的目标是:在 Wayland 下基于平铺式窗口管理器 Sway 构建一个基本可用的桌面环境。
那么话不多说,直入正题。制作安装 U 盘、分区等步骤各人各机需求不同,所以我们跳过这两步,从 Arch Wiki 的 Installation 一节开始。
¶安装系统
假设现在你已经在 live 系统内,连上了网,对好了时,分好了区,把根文件系统装载到 /mnt
,把 EFI 文件系统装载到 /mnt/boot
。
2021 年的 live 系统已经自带了 reflector,用来自动选择“最好的”镜像源。然而,reflector 在国内的效果往往并不好。个人建议手动选择。
1# systemctl disable --now reflector.service reflector.timer
2# tar -xf /var/cache/pacman/pkg/pacman-mirrorlist-* etc/pacman.d/mirrorlist
3# cp -f etc/pacman.d/mirrorlist /etc/pacman.d/mirrorlist
4# vim /etc/pacman.d/mirrorlist # 选择你需要的镜像源
安装基础软件包(包括 base-devel
)、内核、固件、文本编辑器(我选择 Vim)、无线网络管理器(我选择 iwd,不是笔记本就不需要了)、文档查看器等。
1# pacstrap /mnt base linux linux-firmware \
2 base-devel vim iwd man-db man-pages texinfo
下面从 chroot 开始到设置 root 密码为止都和 Arch Wiki 的安装指南没有区别,所以直接看安装指南吧:Configure the system。
安装 boot loader 和 microcode。为了简单起见,我们使用 GRUB,并且不启用 Secure Boot。如果你想让 Arch 与 Windows 11 组成双系统,请自行学习 Secure Boot 的配置方法。
1# pacman -S grub efibootmgr os-prober
2# echo 'GRUB_DISABLE_OS_PROBER=false' >> /etc/default/grub
3# pacman -S intel-ucode # 或者 amd-ucode,取决于你的 CPU 品牌。
4# grub-install --target=x86_64-efi --efi-directory=/boot --bootloader-id=GRUB
5# grub-mkconfig -o /boot/grub/grub.cfg
最后一行指令会自动检测到已安装的 Windows。如果想要之后再安装 Windows,可以在安装后重新执行这行指令。下面退出 chroot 环境,重启。
1# exit
2# reboot
¶基础配置
现在你已经启动到刚刚安装的新系统。第一步是连上网。如果你使用 Wi-Fi,那么首先用 iwctl
连接 Wi-Fi,记住网络接口名。如果你使用有线网络,那么插上网线,用 ip link
查看网络接口名。编辑 /etc/systemd/network/<网络接口名>.network
:
1[Match]
2Name=<网络接口名>
3
4[Network]
5DHCP=yes
6IPv6PrivacyExtensions=true
然后让 systemd-networkd
重新加载配置文件:
1# networkctl reload
现在你应该已经连上网了。下面设置用户:
1# useradd -m -G wheel video -s /bin/bash <用户名>
2# passwd <用户名>
给予新用户 sudo
权限(把 vim
换成你安装的文本编辑器,下同):
1# EDITOR=vim visudo # 取消注释 %wheel ALL=(ALL) ALL 一行
安装 polkit
来让新用户有权开关机。
1# pacman -S polkit
添加 archlinuxcn
源。向 /etc/pacman.conf
末尾加入以下内容(可自行选择和调整镜像顺序):
1[archlinuxcn]
2Server = https://mirrors.sjtug.sjtu.edu.cn/archlinux-cn/$arch
3Server = https://mirrors.ustc.edu.cn/archlinuxcn/$arch
刷新缓存,安装 archlinuxcn-keyring
,然后退出 root 用户,重新登录到新用户。
1# pacman -Syy archlinuxcn-keyring
2# exit
安装 AUR helper,这里选择 paru
。
1$ sudo pacman -S paru
2$ mkdir -p ~/.config/paru
3$ cp /etc/paru.conf ~/.config/paru/paru.conf
按自己的需要编辑 ~/.config/paru/paru.conf
,尤其是要配置 AUR 镜像。我的配置:paru.conf
。
配置 Bash 自动补全和历史记录:
1$ paru -S bash-completion # 把 paru 换成你安装的 AUR helper 或 sudo pacman,下同
2$ paru --aur -S bash-complete-alias # 可选,需要 AUR helper 或手动安装
接下来编辑 ~/.bashrc
。下面的是我的配置,$PS1
和命令别名均可根据自己的需要调整。
1# If not running interactively, don't do anything
2[[ $- != *i* ]] && return
3
4set -o noclobber
5shopt -s checkwinsize
6shopt -s expand_aliases
7
8PS1="\[$(tput setaf 6)\]\w\[$(tput setaf 2)\] \\$ \[$(tput sgr0)\]"
9HISTCONTROL=ignoreboth:erasedups
10HISTIGNORE='\: *:\:'
11HISTFILESIZE=
12HISTSIZE=
13HISTTIMEFORMAT="[%F %T] "
14PROMPT_COMMAND="history -a; $PROMPT_COMMAND"
15
16alias ls='ls --color=auto'
17alias la='ls -A --color=auto'
18alias ll='ls --color=auto -Al'
19alias userctl='systemctl --user'
20alias :q=exit
21
22# 这部分是用来自动补全命令别名的,需要对每个别名分别设置
23# 如果没有安装 bash-complete-alias,则不需要下面这部分
24. /usr/share/bash-complete-alias/complete_alias
25complete -F _conplete_alias la
26complete -F _complete_alias ll
27complete -F _complete_alias userctl
其它常用命令行工具均可按需安装,这里就不再展开。
电源管理所需要的配置在不同硬件之间差别很大,我现在的笔记本用的是 Intel 处理器,下面是我使用的电源管理服务:
1$ paru -S thermald cpupower tlp
2$ sudo systemctl enable --now thermald cpupower tlp
同时建议修改 /etc/systemd/logind.conf
里的 ACPI 事件设置,我修改了下面两条:
1HandlePowerKey=ignore
2HandleLidSwitch=lock
基础配置差不多就是这些。接下来就是这篇博客真正的重头戏了。
¶图形界面
首先安装显卡驱动。这一步同样与硬件高度相关,这里仅以 Intel 集显为例,其它显卡的用户可以参考 Arch Wiki 的这一节自行调整。
1$ paru -S mesa libva-intel-driver
安装 Sway、Xwayland、Qt5 的 Wayland 后端、终端模拟器和基础字体。
1$ paru -S sway xorg-xwayland qt5-wayland qterminal \ # 换成你喜欢的终端模拟器
2 noto-fonts noto-fonts-cjk noto-fonts-emoji # 可以换成你喜欢的字体,但要有中英文
接下来是重点!就本文写作时而言,官方库内还没有原生支持 Wayland 的显示管理器(唯一一款原生支持 Wayland 的需要自行编译和很复杂的配置,其它的虽然能启动 Wayland 桌面环境但本身必须运行在 X server 下),因此我们将不使用显示管理器,直接在登陆 TTY 后从 TTY 启动 Sway。下面需要手动编写一些 Systemd 单元文件。
~/.config/systemd/user/sway-session.target
:
1[Unit]
2Description=Sway session
3Documentation=man:systemd.special(7)
4BindsTo=graphical-session.target
~/.config/systemd/user/graphical-session.target.d/override.conf
:
1[Unit]
2BindsTo=sway-session.target
~/.config/systemd/user/sway-autostart.target
:
1[Unit]
2Description=Sway session autostart
3Documentation=man:systemd.special(7)
4BindsTo=xdg-desktop-autostart.target graphical-session.target
~/.config/systemd/user/xdg-desktop-autostart.target.d
:
1[Unit]
2BindsTo=sway-autostart.target
~/.config/systemd/user/sway.service
:
1[Unit]
2Description=Sway
3Documentation=man:sway(5)
4
5[Service]
6Type=simple
7ExecStart=sway
8ExecStopPost=systemctl --user stop sway-session.target
9ExecStopPost=systemctl --user unset-environment DBUS_SESSION_BUS_ADDRESS DISPLAY SWAYSOCK WAYLAND_DISPLAY
10
11[Install]
12WantedBy=graphical-session.target
配置 Sway:
1$ userctl enable sway # 如果没有设置别名 userctl,就换成 systemctl --user,下同
2$ mkdir -p ~/.config/sway
3$ cp /etc/sway/config ~/.config/sway/config
编辑 ~/.config/sway/config
。set $term
处:
1# Your preferred terminal emulator
2set $term qterminal
# Exit sway
处:
1# Exit sway (logs you out of your Wayland session)
2bindsym $mod+Shift+e exec swaynag -t warning \
3 -m 'Do you really want to exit sway? This will end your Wayland session.' \
4 -b 'Yes, exit sway' \
5 'systemctl --user stop sway-session.target; swaymsg exit'
文件末尾:
1# Begin autostart
2exec sleep 5 && systemctl --user start sway-autostart.target
除了上述几处之外,你也可以在这里根据自己的需求修改键位、壁纸、Hi-DPI 缩放、触摸板、键盘 Numlock 等配置,详见 Arch Wiki 页面和 Sway 文档。
编辑 ~/.config/environment.d/env.conf
设置环境变量(这里有一些变量要后面才会用到,这里提前加入以免重复累赘):
1LANG=zh_CN.UTF-8
2XDG_CURRENT_DESKTOP=sway
3QT_QPA_PLATFORM=wayland-egl
4SDL_VIDEODRIVER=wayland
5MOZ_ENABLE_WAYLAND=1
6GTK_IM_MODULE=fcitx
7QT_IM_MODULE=fcitx
8XMODIFIERS=@im=fcitx
9SDL_IM_MODULE=fcitx
编辑 ~/.bashrc
:
1 # If not running interactively, don't do anything
2 [[ $- != *i* ]] && return
3
4+if [ -z $DISPLAY ] && [ "$(tty)" = "/dev/tty1" ]; then
5+ export EDITOR=vim
6+ export PATH=$HOME/.local/bin:$PATH
7+ systemctl --user import-environment \
8+ XDG_SESSION_ID XDG_RUNTIME_DIR XDG_SESSION_TYPE XDG_SEAT \
9+ PATH EDITOR
10+ systemctl --user start sway-session.target
11+fi
最后,reboot
重启电脑。重新登陆,你应该能看到 Sway 自动启动了。
下面解释一下上述配置的原理。Sway 启动需要一些环境变量,这些环境变量在每次登陆时可能有变化,并且 Systemd 的服务运行环境默认并没有设置这些环境变量,因此我们需要在登陆到 Bash 时将这些变量导入到 Systemd 的环境中,然后启动 Sway session。一些 TTY 下与图形环境共享的环境变量也应在这里设置并导入。而仅限图形环境的变量则可在 Systemd 的环境配置文件夹 ~/.config/environment.d/
下设置。sway-session.target
启动会带动 graphic-session.target
这个特殊目标启动,进而启动我们已经启用的 sway.service
,也就是启动 Sway。Sway 在读取到配置文件的末尾时启动 sway-autostart.target
,从而启动之后需要安装的各种自启应用。
为什么要搞得那么复杂?为了符合 Systemd 的标准,从而更方便与之后安装的各种应用协调。
现在你已经进入 Sway,使用 Meta+Enter(即 Win+Enter)启动终端模拟器。首先安装音频服务并启动。
1$ paru -S pipewire pipewire-alsa pipewire-pulse
2$ userctl start pipewire pipewire-pulse pipewire-media-session
还有一些不需要怎么配置的系统服务,如状态栏(这里选择 waybar
)、消息通知 daemon(这里选择 mako
)、xdg-desktop-portal
。
1$ paru -S --asdeps xdg-desktop-portal-wlr
2$ paru -S otf-font-awesome waybar mako xdg-desktop-portal
编辑 ~/.config/sway/config
的 # Status Bar
部分来应用 waybar
:
1#
2# Status Bar:
3#
4bar {
5 swaybar_command waybar
6}
Meta+Shift+C 重载配置文件,就能看到新的状态栏了。可以分别编辑 ~/.config/waybar/{config,style.css}
和 ~/.config/mako/config
来自定义它们的外观。
下面安装应用启动器,这里选择 bemenu
。
1$ paru -S bemenu j4-dmenu-desktop-git
编辑 ~/.config/sway/config
的 set $menu
处:
1# Your preferred application launcher
2# Note: pass the final command to swaymsg so that the resulting window can be opened
3# on the original workspace that the command was run on.
4set $menu j4-dmenu-desktop \
5 --dmenu='bemenu -i -l10 --scrollbar autohide' \
6 --wrapper 'swaymsg exec'
再次重载配置文件,现在你可以用 Meta+D 打开应用启动器了。
现在你可以安装 firefox
(以及 firefox-i18n-zh-cn
)并用应用启动器启动来继续阅读本文的下一部分了。
¶应用软件
这一节将会介绍一些比较难配置,或者需要注意的应用的安装配置。这一节的各部分基本是相互独立的。
¶亮度与音量调节
我的笔记本上有亮度和音量调节的按键,这些按键的功能在 Sway 上需要手动实现。
首先我们要给予用户修改亮度的权限。编辑 /etc/udev/rules.d/backlight.rules
:
1SUBSYSTEM=="backlight", ACTION=="add", \
2 RUN+="/bin/chgrp video /sys/class/backlight/%k/brightness", \
3 RUN+="/bin/chmod g+w /sys/class/backlight/%k/brightness"
重载 udev 规则:
1$ sudo udevadm control --reload
2$ sudo udevadm trigger
接下来,我们还希望使用这些按键时能有屏幕反馈。可以用 Wob 实现简单的亮度/音量提示框。
1$ paru -S wob
编写一些 Systemd 单元文件。~/.config/systemd/user/[email protected]
:
1[Socket]
2ListenFIFO=%t/wob@%i.sock
3SocketMode=0600
4
5[Install]
6WantedBy=sockets.target
~/.config/systemd/user/[email protected]
:
1[Unit]
2Description=Wob
3BindsTo=graphical-session.target
4
5[Service]
6Type=simple
7StandardInput=socket
8ExecStart=wob --anchor top --border-color "#A0000000" --background-color "#A0000000" --bar-color "#A0FFFFFF"
然后分别对亮度和音量启用 [email protected]
:
1$ userctl enable --now [email protected] [email protected]
现在这两个服务会监听 $XDG_RUNTIME_DIR/wob@{brightness,volume}.sock
,在读取到数字时显示亮度和音量。
为了修改亮度,我们还需要安装一个命令行工具 acpilight
:
1$ paru -S acpilight
最后向 Sway 配置文件中加入以下几行来监听快捷键:
1# Light adjustment
2bindsym --locked XF86MonBrightnessUp exec xbacklight -inc 2 && xbacklight -get > $XDG_RUNTIME_DIR/[email protected]
3bindsym --locked XF86MonBrightnessDown exec xbacklight -dec 2 && xbacklight -get > $XDG_RUNTIME_DIR/[email protected]
4
5# Audio adjustment
6bindsym --locked XF86AudioMute exec pactl set-sink-mute 0 toggle
7bindsym --locked XF86AudioLowerVolume exec pactl set-sink-volume 0 -5% \
8 && pactl list sinks | grep -Pom1 "\d+(?=%)" > $XDG_RUNTIME_DIR/[email protected]
9bindsym --locked XF86AudioRaiseVolume exec pactl set-sink-volume 0 +5% \
10 && pactl list sinks | grep -Pom1 "\d+(?=%)" > $XDG_RUNTIME_DIR/[email protected]
¶锁屏
在 Sway 中,锁屏也需要手动配置。这里使用 Sway 官方开发的 swaylock
和 swayidle
。
1$ paru -S swaylock swayidle
这两个工具结合使用可以实现非常复杂的锁定逻辑。这里我们要实现的功能是这样的:
- 当按下电源按钮,关闭屏幕且不锁定;
- 当按下 Meta+L,锁定但不关闭屏幕;
- 当合上屏幕时,锁定;
- 当持续 5 分钟无活动时,锁定并关闭屏幕。
下面编写一些 Systemd 单元文件。~/.config/systemd/user/sway-close-display.service
,用来实现第一点需求:
1[Unit]
2Description=Swayidle close display
3BindsTo=graphical-session.target
4
5[Service]
6Type=simple
7ExecStart=swayidle -w timeout 0 'close-display' resume 'swaymsg "output * dpms on"'
8
9[Install]
10WantedBy=xdg-desktop-autostart.target
~/.config/systemd/user/sway-idle-lock.service
,用来实现其余三点:
1[Unit]
2Description=Swayidle idle lock
3BindsTo=graphical-session.target
4
5[Service]
6Type=simple
7ExecStart=swayidle -w timeout 300 'close-display' timeout 301 'swaylock' resume 'swaymsg "output * dpms on"' before-sleep 'swaylock' lock 'swaylock'
8
9[Install]
10WantedBy=xdg-desktop-autostart.target
启用这两个服务:
1$ userctl enable --now sway-close-display sway-idle-lock
还要编写两个辅助脚本。~/.local/bin/close-display
,用来实现流畅美观地关闭屏幕:
1#!/bin/bash
2orig_value=$(xbacklight -get)
3xbacklight -set 0 -fps 60
4swaymsg 'output * dpms off'
5xbacklight -set $orig_value
~/.local/bin/lock
,用来手动触发关闭屏幕和锁定:
1#!/bin/bash
2kill -s SIGUSR1 \
3 $(systemctl --user show $1 --property=MainPID | cut -d'=' -f2)
最后向 Sway 配置文件加入以下几行监听快捷键:
1# Lock
2bindsym --locked $mod+l exec swaylock
3bindsym --locked XF86PowerOff exec lock sway-close-display
完成。你可以编辑 ~/.config/swaylock/config
修改锁屏的外观。
¶截图
就本文写作时而言,在 Sway 下暂时还没有很完善的截图解决方案。下面给出一种做法。
1$ paru -S grim slurp grimshot swappy
编辑 Sway 配置文件绑定快捷键:
1# Screenshot
2bindsym Print exec grimshot copy screen
3bindsym $mod+Print exec grimshot save window - | swappy -f -
4bindsym $mod+Shift+Print exec sleep 3 && grimshot save window - | swappy -f -
这么做可以实现:
- 当按下键盘上的 Print 键时,全屏截图并复制;
- Meta+Print,选框截图并使用 Swappy 编辑;
- Meta+Shift+Print,倒计时三秒后选框截图并用 Swappy 编辑。
然而由于 grimshot
是基于 grim
和 slurp
两个工具来实现选框截图的,是在选择好区域后再截图,而非先固定截图再选择区域裁剪,这就导致第三个快捷键的目的——给右键菜单等鼠标操作后会消失的控件截图——并不能实现。
¶剪贴板管理器
Wayland 服务器不提供剪贴板管理功能,需要安装剪贴板管理程序才能在剪贴来源程序关闭后保存剪贴板内容。
1$ paru -S copyq
用应用启动器启动 CopyQ,在文件 > 首选项 菜单内启用自动启动。
已知问题是 CopyQ 的菜单栏菜单总是出现在上方。
¶输入法
1$ paru -S fcitx5-im fcitx5-chinese-addons
用应用启动器启动 Fcitx 5。所需的环境变量已经在前面配置好。下次启动 Sway 时 Fcitx 5 会自动启动。
已知问题是在 Firefox 的拓展的弹框内(例如 Saladict)输入法选项框无法显示。
¶基于 Chromium 的应用
目前大部分基于 Chromium 的应用应该都还需要手动添加命令行参数才能原生运行在 Wayland 下,下面以 Visual Studio Code 为例。
1$ paru -S visual-studio-code-bin
2$ mkdir -p ~/.local/share/applications
3$ cp /usr/share/applications/visual-studio-code* ~/.local/share/applications/
编辑 ~/.local/bin/code
:
1#!/bin/bash
2/usr/bin/code --enable-features=UseOzonePlatform --ozone-platform=wayland "$@"
~/.local/share/applications/visual-studio-code.desktop
:
1@@ -5 +5 @@
2-Exec=/opt/visual-studio-code/code --no-sandbox --unity-launch %F
3+Exec=code --no-sandbox --unity-launch %F
4@@ -17 +17 @@
5-Exec=/opt/visual-studio-code/code --no-sandbox --new-window %F
6+Exec=code --no-sandbox --new-window %F
~/.local/share/applications/visual-studio-code-url-handler.desktop
:
1@@ -5 +5 @@
2-Exec=/opt/visual-studio-code/code --no-sandbox --open-url %U
3+Exec=code --no-sandbox --open-url %U
现在 VSCode 就能原生在 Wayland 下运行了。
已知问题是 VSCode 内无法使用输入法。
¶代理
这里使用 Qv2ray 来图形化管理 V2ray。
1$ paru -S qv2ray-dev-git xray # 或者 v2ray
从应用管理器启动 Qv2ray,在首选项中启用登陆时启动。如果使用 xray 则还要在 首选项 > 内核设置 中更换内核。
¶其它常用应用
我的选择:
1$ paru -S gthumb # 图片查看器
2$ paru -S thunar gvfs trash-cli # 文件管理器和回收站
3$ paru -S mpv # 音乐和视频播放器,等到 VLC 原生支持 Wayland 之后会换成 VLC
至于更多的……自己探索吧。
¶个性化
这里的个性化指的是 GTK 和 Qt 两大 GUI 框架的主题。我安装的主题:
1$ paru -S arc-gtk-theme arc-icon-theme
GTK 在 Wayland 下的主题设置比较麻烦,因为 GTK3 在 Wayland 下有特别的读取主题方式。我选择自己写一个脚本设置主题。
1#!/bin/bash
2
3gtk2_config="$HOME/.gtkrc-2.0"
4gtk3_config="$HOME/.config/gtk-3/settings.ini"
5gnome_schema="org.gnome.desktop.interface"
6map=(
7# gtkrc-key:gsettings-key:value
8 gtk-theme-name:gtk-theme:Arc-Dark
9 gtk-icon-theme-name:icon-theme:Arc
10 "gtk-font-name:font-name:Sans 11"
11 gtk-cursor-theme-name:cursor-theme:Adwaita
12)
13
14rm -f $gtk2_config
15rm -f $gtk3_config
16#mkdir -p $(dirname $gtk3_config)
17#echo "[Settings]" >> $gtk3_config
18for i in "${map[@]}"; do
19 #echo $(echo $i | cut -d':' -f1) = \"$(echo $i | cut -d':' -f3)\" >> $gtk2_config
20 #echo $(echo $i | cut -d':' -f1) = $(echo $i | cut -d':' -f3) >> $gtk3_config
21 gsettings set $gnome_schema $(echo $i | cut -d':' -f2) "$(echo $i | cut -d':' -f3)"
22done
有 GTK2 和在 XWayland 下使用 GTK3 需求的可以取消注释对应的行。这个脚本只需要在修改配置时运行一次,不需要每次启动都运行。
Qt 的主题设置基本和 X11 下相同,我的选择:
1$ paru -S qt5ct kvantum-qt5
在 ~/.config/environment.d/env.conf
内加入 QT_QPA_PLATFORMTHEME=qt5ct
,用 Kvantum Manager 选择仿 Arc Dark 主题,用 Qt5ct 选择 Kvantum 主题引擎。
Fontconfig 设置之类的,都与 X11 下没有区别,可以直接参考 Arch Wiki。
¶已知问题
- 前面已经提到的问题;
- 当 Sway 设置了 Hi-DPI 缩放时,运行在 XWayland 下的程序会模糊。