Play With Gentoo

整了个新设备, 准备完全 get rid of windows, 打游戏什么的用原来的老电脑, 反正也不经常玩. 这台电脑就不装 Ubuntu 了, 远离 snap, 远离 gnome (主要问题是 gnome-shell 内存泄漏). 而且最近两年几乎拿 Linux 当主力, 想着把系统打造成完全符合自己想法的东西, 轻量且现代, 但是在一些 “捆绑了许多东西” 的发行版上还是比较难以实现. 所以最后决定装个 Gentoo, 折腾折腾还能学点东西.

  • 趁着年轻喜欢折腾
  • systemd no! OpenRC yes!
  • 本地编译, 针对设备优化, 只编译自己想要的功能
  • world file, 如果以后换设备可以直接 copy, 一键构建同样的系统 (配置文件除外)
  • 滚动更新

用了一段时间来补充一个, portage 是真的爽, 巨爽的包管理器, 再也不用担心各种版本各种依赖的问题了

指导思想是 “轻量且现代” (可能导致激进), 目前有如下想法 (随着安装进度更新):

  1. DE no, WM yes.

说实话桌面环境中的一些功能我完全不用, 比如桌面图标, gnome 的 dock. 只需要有个状态栏, 能够启动程序就行. 当然 DE 带的一些软件如文件管理器, terminal 等, 还是需要的. 不过这东西都可以自己选择. 搜了一下发现除了 DE 以外, 还有更轻量的 窗口管理器Window Manager, 能够独立于 DE 运行. 正好符合我的需求.

  1. X no, Wayland yes.

可能是我用的 gnome 直接支持 Wayland, 所以我没体验到 X 的弱势, 不过据说对多显示器支持不太行, 以及有些历史问题? 所以尝试一些新东西, 如果可以的话直接抛弃 X.

  1. btrfs

btrfs 的很多现代化功能看上去十分诱人, 比如 CoW, 快照, 压缩, 而且新的 kernel 增加了许多 btrfs 的支持, 那为什么不玩玩 btrfs 呢?

  1. only QT

Ubuntu 自带 GTK2 3 4, 以及自己装软件的时候貌似还装上了 QT. 想着能不能只要一个 GUI 库. 大概了解了一下, 决定使用 QT 而不是 GTK.

  1. keyboard driver

电脑高手谁用鼠标啊

  1. XDP

既然是从源码安装了, 那不遵守 XDP 的东西我也可以给 patch 上让他遵守 从一个硬编码改到另一个硬编码.

其实基本上也就对着 官方手册 来, 记录一点自己的过程.

首先做一个启动盘. 由于有另一台电脑辅助, 所以不需要图形界面, 镜像就选择最小化 cd. linux 下的刻录工具官方建议用 cdrecord, 装了一下发现貌似改名了, 然后也不会用, 遂放弃, 跑去 Windows 下用 UltraISO 了. 需要关闭 BIOS 的安全启动, 才可以从 U 盘启动.

第一次 iso 下成了 x86 架构的, grub 之后光标在左上角闪了一下就卡住了. 奇怪的是老电脑又能正常启动, 吓得我以为新电脑硬件什么的有问题用不了 (电脑: 不是我有问题是你脑子有问题). 可能是新电脑仅支持 UEFI, 老电脑我记得启动方式选的是 both. 不懂.

分区在仔细思考过后决定只有 EFI, swap 和根, 相当于不分区, 不纠结给 /home 多少的问题. 文件系统打算用 btrfs.

先把已有的分区抹掉, 然后创建一个 EFI 系统分区, 用于 UEFI 的启动. 原先自带系统 EFI 分区大小是 260M, 这里就也用 260M 吧 (不是很懂为什么手册建议 1G, 老电脑双系统 260M 都绰绰有余).

接下来是 swap 分区. 之前编译 WebKit 把内存跑没了, 又挂了 16G 的 swap file 才勉强编译完. 以及 btrfs 创建 swap file 还得搞 nocow, 怕忘了, 所以不如 swap 分区就给大一点, 2 倍物理内存, 32G.

最后剩下的创建一个根分区, 类型是 btrfs.

stage3 大概就是提供了一个最小的文件环境, 包含有 /etc, /var 等等必要的东西. stage3 有多种选择, 这里选择 OpenRC 不带桌面环境的.

之前搞了一次带桌面环境的, 更新系统软件的时候 qt 依赖 X, 但是我不要 X. 所以不选桌面环境了. qt 的问题之后再说.

把根分区挂载上, mount /dev/nvmen1p3 /mnt/gentoo, 然后把 stage.tar 解压到这里, 以后这里就是我们的系统根目录了!

技巧

如果要用 btrfs 的快照啥的功能, 其实应该创建用于挂载根目录的子卷. 具体来说需要 mount -t btrfs 挂载, 然后在挂载点中运行 btrfs subvolume create @, 这将在挂载点 /mnt/gentoo 下创建名为 @ 的子卷, 表现就是一个文件夹, 然后 stage 解压到 @ 中. (不命名为 @ 而是其他名字也是可以的)

剩下到 btrfs 快照 的部分说.

之后更新的, 已经忘了, TODO

按照流程把 ebuild 软件仓库和 DNS 信息复制过去, 接下来就要在我们之后的系统进行工作了. arch-chroot /mnt/gentoo 过去即可.

1
2
emerge-webrsync
emerge --sync

eselect 选择最普通的啥也没有的 profile. 这里先配置再更新 @world 集.

Gentoo 的一切都是本地编译, 而且能够指定编译参数. 参考了一下其他教程的, 最后配置如下:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
COMMON_FLAGS="-march=native -O2 -pipe"
CFLAGS="${COMMON_FLAGS}"
CXXFLAGS="${COMMON_FLAGS}"
FCFLAGS="${COMMON_FLAGS}"
FFLAGS="${COMMON_FLAGS}"
MAKEOPTS="-j8"

USE="-bindit -X -systemd"
ACCEPT_KEYWORDS="~amd64"
ACCEPT_LICENSE="*"

L10N="en-US zh-CN en zh"

VIDEO_CARDS="intel i965 iris"

GRUB_PLATFORMS="efi-64"

LC_MESSAGES=C.utf8

GENTOO_MIRRORS="https://mirrors.ustc.edu.cn/gentoo/ \
    rsync://rsync.mirrors.ustc.edu.cn/gentoo"

FEATURES="ccache -test"
CCACHE_DIR="/var/cache/ccache"

MAKEOPTS="-j8" 是指定几个线程编译, 之前一直都直接有多少核开多少个, 直到看到手册里写的:

引用
警告
大量的 job 显著消耗内存。建议每个 job 至少有 2 GiB RAM (所以,-j6 至少 需要 12 GiB)。避免内存溢出,根据可用内存降低 job 数量。

怪不得之前编译 WebKit 的时候要这么多内存

老老实实用 -j8.

USE 中排除对 X 和 systemd 的支持, bindist 不知道是啥, 反正说建议 ban 了. USE 是程序编译会用的 标志Flags, - 是移除, 没有 - 的话是添加. make.conf 中设置的是全局的.

ACCEPT_KEYWORDS="~amd" 前面的 ~ 的意思是用软件的 test 版本, 一般来说会比较新, amd 不用说是架构.

ACCEPT_LICENSE="*" 接受一切 LICENSE

L10N="en-US zh-CN en zh" 是设置语言支持, 把中文加上

VIDEO_CARDS="intel i965 iris" 是显卡, intel 的都加上一个 i965. 看到一份加了 iris 的, 瞟了一眼触控板旁边的贴纸, 有 iris 字样, 加上加上. (不打游戏不跑 AI, 特地选的没 N 卡的电脑)

GRUB_PLATFORMS="efi-64" grub UEFI 64 引导需要. (之前折腾的时候看了还只能选 UEFI 64 的)

除了 make.conf 中能够配置以外, 在 /etc/portage/package.use/ 中也能配置, 比如按照教程添加的 CPU_FLAGS_*. 除了这个以外, 个人还加入了 pyton 和 ccache 的配置.

/etc/portage/package.use/python:

1
2
*/* PYTHON_TARGES: -* python3_11
*/* PYTHON_SINGLE_TARGET: -* python3_11

这是因为当前版本的 ebuild 会使用 3.11 和 3.12 两个版本的 python, 而我希望电脑里只有一个 python. 经过一些尝试 (重装了好几次), 发现有些基础的软件还不支持 python3.12, 所以这里把所有 FLAGS 都减去, 只添加一个 3.11.

前面的 */* 是匹配所有软件包的意思. Gentoo 软件包的格式类似 type/name, 比如 dev-lang/python.

然后是 ccache. 这是用于加速编译的软件, 用 emerge --ask ccache 安装. 然后准备一个缓存文件夹, 比如:

1
2
3
mkdir -p /var/cache/ccache
chown root:portage /var/cache/ccache -R
chmod 2775 /var/cache/ccache -R

最后在 /etc/portage/package.use/ccache 中写:

1
2
*/* FEATURES: ccache -t
*/* CCACHE_DIR: /var/cache/ccache/

使用 emerge --ask --verbose --update --deep --newuse @world 更新 @world 集. Gentoo 用 @world 来代指所有软件, 包括系统所需的 (@system) 和自行安装的 (/var/lib/portage/world) 以及他们需要的依赖包.

--ask 安装前会停下来询问, --verbose 输出更多信息 (可以看到一些软件的最小依赖, 包名后面红色的 USE FALGS), --update 是更新, --newuse 是某些软件修改了 USE 后就重新编译 (当然包括全局修改的), --deep 会去更新依赖, 还可以加数字指定层级, 不加就是所有.

直接按照它这个来还是会给我装一个 python3.12, 即使貌似没有任何软件依赖它. 所以先把 --deep 去掉, 然后对每个需要更新的软件修改 --deep 的层级, 避免安装新的 python()

洁癖是这样的

觉得麻烦, 后来更新软件什么的都要注意, 随放弃.

没啥好说的, 跟着手册就是. 区域只选了 UTF8 的, 应该不会有问题吧.

装了个 linux-firmware, 后来发现没有声音. 一看 dmesg 发现少一个叫 sof 的固件驱动. 一顿搜索发现得安装 sof-firmware. 其他暂时没发现.

现在使用的内核还是 livecd 里的, 我们的系统还没有一个 kernel.

微码看了一下说在启动时期越早越好, 到内核了都已经多晚了, 就不编译进内核了. 等有机会整整在引导的时候装.

自己编译内核虽然可以针对当前设备的硬件, 从而提高效率, 但是这工作量貌似有点大了. 以及内核编译参数有一万个, 想想也看不动, 不如装好一个先玩着, 后面还有很多东西要搞, 等之后有需求再自己调整内核. 既然没有定制需求, 那也就不编译了, 直接用 gentoo-kernel-bin. 在 merge kernel 之前, 先 merge 一个 btrfs-prog, 以支持 btrfs. (貌似是最后生成 initramfs 要用? 如果先 merge 了内核, 可以 emerge --config gentoo-kernel(-bin) 重新配置并生成 initramfs) 最后应该会在 /boot 下生成一些 initramfs.

内核模块也没什么特殊需求.

最开始用了 genfstab 搞了一个能用的, 具体内容放到后面 btrfs 快照 的时候说.

引导就用 grub. 首先 mkdir /efi && mount /dev/nvme0n1p1 /efi 将引导分区挂载到 /efi (其实挂载到 /boot/efi 更好一点?), 然后执行以下命令安装并自动配置:

1
2
grub-install --target=x86_64-efi --efi-directory=/efi
grub-mkconfig -o /boot/grub/grub.cfg

引导设置完以后, 就是装完了. reboot!

装完系统第一件事就是备份一个, 以免今后被完坏重装. btrfs 天然支持快照, 于是花了一点时间了解了一下.

btrfs 有 子卷subvolume 这个概念, 相当于在分区里分小区? 子卷支持嵌套, 一整个大的分区也叫一个子卷, 也就是我这里的 /dev/nvme0n1p3, 一个快照也是一个子卷, 所以备份快照什么的最好以子卷为单位. 如果分区完不做任何操作, 那这个分区就是根子卷. 根子卷的 subvolid 是 5. 子卷的表现就是一个文件夹. (自己都不知道自己在说什么)

在顶级子卷下新建子卷, 可以更好管理. 这里选择称为扁平结构的子卷方式:

根子卷
|- @
|- @home
|- @root
|- ...

只有一层, 不进行更多嵌套.

子卷可以当成一个卷/分区来用, 可以挂载到任意地方. 比如上述结构, 我希望把子卷 @ 挂载到 / 上当作根目录, 把 @home 挂载到 /home 上, @root 挂载到 /root 上.

为了方便, 还把根子卷挂载到了 /mnt/btrfs 上.

最开始当然只有一个根子卷. 可以将其挂载到某处, 比如 /mnt/btrfs, 然后在这里 btrfs subvolume create ./<subvolume-naem> 创建子卷, 表现就是能在当前目录下看到一个文件夹.

如果一开始就把子卷 @ 当成根目录, 把 stage3.tar 解压到这里, 就方便得多了. 如果已经在根子卷里有一个根目录了的话, 使用 snapshot 功能也可以转换一下.

具体来说就是 btrfs subvolume snapshot ./ ./@, 这样就把 ./ 目录的快照打在了 ./@ 下. (为了安全和可行性, 我实现这个操作是在 livecd 里进行的, 将 /dev/nvme0n1p3 挂载, 然后进入目录执行快照, 不知道直接在系统搞里会发生什么)

现在 ./ (挂载点, 可能是 /mnt/gentoo) 下不仅有 bin, etc 这些, 还多了一个 @ 目录, 可以 cd 进去看, 就和快照前的根目录 (/mnt/gentoo) 一样. 然后可以将其他东西删掉, 只留 @ 了.

挂载子卷需要指定 id 或者名字. 如果用 genfstab 的话可以看到选项中是有 subvolid=5,subvol=/ 的. subvolid 和 subvol 都可以指定子卷. btrfs subvolume list <path> 可以查看子卷, 包括 id 和名字, subvol 就是通过名字确定的子卷.

这样一来, fstab 大概写成这样:

1
2
3
/dev/nvme0n1p3    /             btrfs     subvol=/@         0 0
/dev/nvme0n1p3    /mnt/btrfs    btrfs     subvolid=5        0 0
/dev/nvme0n1p3    /home         btrfs     subvol=/@home     0 0

然后想想需要备份哪些, 根目录肯定是要的, /home/opt 可以单独备份, 不参与进根目录的. /root 不放什么东西没有备份必要, 还有 /var/cache/ccache 是缓存, 而且会频繁变化, 不需要备份, /var/log 一堆日志罢了也不需要备份. (就没怎么翻过日志找问题)

所以搞了 @, @home, @root, @opt, @ccache, @log 这些子卷, 并且在 fstab 中挂载到相应的位置.

挂载选项是 rw,noatime,ssd,sapce_cache=v2,compress=zstd,discard=async, 其中 rw 是权限, noatime 是不使用时间戳, 这样 CoW 的话不会有多余的时间戳需要存, compress=zstd 是用 zstd 标准进行压缩 (也有其他压缩方法, 没了解过, 反正压缩了就行), 其他是一些 (和 ssd 相关的) 优化.

然后还挂了一个 tmpfs /tmp, 编译的时候会使用 /tmp, 直接挂到内存中去可能能够加速编译.

备份工具使用 btrbk (timeshift 没有 cli, 于是找到个专门针对 btrfs 的工具) (实际上也可以不使用工具, 直接 btrfs subvolume snapshot 也行)

工具怎么用就不说了, 由于暂时只有搞坏了需要滚回去, 而没有备份重要文件的需求, 所以只搞快照就行. 贴一下配置:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
transaction_log         /var/log/btrbk.log
lockfile                /var/lock/btrbk.lock
backend                 btrfs-progs-doas
stream_buffer           256m

snapshot_create         onchange
snapshot_preserve_min   latest
snapshot_preserve       24h 7d 0w 0m 0y

volume /mnt/btrfs
  snapshot_dir  .btrbk_snapshots
  subvolume     @

这样每次打快照, 会将子卷 @ 保存在 /mnt/btrfs/.btrbk_snapshots 下.

恢复是挂载快照子卷, 而不是覆盖回滚的操作.

sudo 要装一些其他库, 而 doas 不需要, 而且 sudo 针对多用户配置功能强大, 但我是单一用户, 有个能用的就行, 所以选择了装 doas 而不是 sudo. 玩点不一样的. doas 还要自己配置, 我就配了个 wheel 用户组可以使用, root 不用密码.

(日常用户配了个 gentoo 命令的补全, root 没补全有点难受, doas 不能和 sudo 一样一段时间内不用输入密码, doas 每次都要输入, 有点麻烦, 于是直接配置 wheel 不用密码了)

日志选了个 sysklogd, 应该也用不到什么特殊的功能, 就最简单的好了.

本来是用 sysklogd 的, 结果它关机的时候可能卡住, 轻则说 sysklogd 结束失败, 重则无法关机. 于是乎换成了 metalog.

时间同步装了一个 chrony, 记得 rc-update add chronyd default.

声音服务, Pipewire 还支持屏幕录制 (需要 xdg-desktop-portl). 还有一个 WirePlumber 用于管理. Pipewire 默认模拟 Pulse 的后端, 因为大多数软件不支持原生 Pipewire. 这也就导致了全局 USE Flag 需要启用 pulseaudiopipewire, 才能让大多数软件正常工作, 比如 OBS.

pulsemixer 可以分应用调整声音 (虽然是 python).

最近更新到 1.2.0 后发现笔记本扬声器没了, 经过三天的搜索和尝试, 终于发现了问题所在: 把 HDMI 线拔了扬声器就恢复了! #4002. pulseaudio 除了可以设置设备以外, 还可以设置 profile 的东西, 相当于是设备集? 接上了 HDMI 显示器之后, 自动切换到了另一个 profile #4031, 这个 profile 里没有扬声器……

pactl list cards 可以看到 profiles:

1
2
3
4
5
6
    Profiles:
                off: Off (sinks: 0, sources: 0, priority: 0, available: yes)
                HiFi (HDMI1, HDMI2, HDMI3, Headphones, Mic1, Mic2): Play HiFi quality Music (HDMI1, HDMI2, HDMI3, Headphones, Mic1, Mic2) (sinks: 4, sources: 2, priority: 10300, available: yes)
                HiFi (HDMI1, HDMI2, HDMI3, Mic1, Mic2, Speaker): Play HiFi quality Music (HDMI1, HDMI2, HDMI3, Mic1, Mic2, Speaker) (sinks: 4, sources: 2, priority: 10200, available: yes)
                pro-audio: Pro Audio (sinks: 5, sources: 3, priority: 1, available: yes)
        Active Profile: HiFi (HDMI1, HDMI2, HDMI3, Headphones, Mic1, Mic2)

可以看到默认的 profile 是没有 speaker 的, 需要切换一下: pactl set-card-profile alsa_card.pci-0000_00_1f.3-platform-skl_hda_dsp_generic 'HiFi (HDMI1, HDMI2, HDMI3, Mic1, Mic2, Speaker)'. 或者使用, pulsemixer, 按 F3 选择 card, 然后回车就能够设置 profile 了.

设置好了下次启动会记住原先设置的, 不需要每次都设置.

1.0.7 版本貌似不会这样处理, 设备直接显示的就是 Speaker + Headphones.

然后就回到了老问题, 启动的时候会静音, 需要按一下静音再取消 #4084. 这个问题最早之前遇到过, 后来我也不知道怎么的又没了. (降级到 1.0.7 版本没有这个问题, 但是 1.2.0 又回来了qaq.)

使用蓝牙耳机还需要配置一下 (已更新到 0.5 版本):

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
# /home/wings/.config/wireplumber/wireplumber.conf.d
monitor.bluez.rules = [
  {
    matches = [
      {
        device.name = "~bluez_card.*"
      }
    ]
    actions = {
      bluez5.auto-connect = [ hfp_hf hsp_hs a2dp_sink hfp_ag hsp_ag a2dp_source ]
      bluez5.a2dp.aac.bitratemode = 1
    }
  }
]

自动切换 A2DP 和 HSP/HFP:

TODO, 还没搞

用了一段时间 wpa_supplicant, cli 有点交互不友好, 本来想换成 network manager, 方便以后可能比赛啥的要配静态 ip. 后来详细看 Gentoo 的默认网络管理工具 Netfirc, 发现是可以配的, 就是需要改配置文件, 不是很方便. 想了想还是用 Netfirc 吧. 然后管理无线网络就用 iwd 了, 直接把 /etc/conf.d/net 中的 modules_wlan0="wpa_supplicant" 换成 modules_wlan0="iwd" 即可, 甚至不需要和 wpa_supplicant 那样额外去配置网卡. 就是网络名称从一个奇怪的名字变成了 wlan0. 注意 rc 要把 net.wlan0 软链接一下 net.lo. iwd 不需要自启动, net.wlan0 会启动它.

(期间还把 dhcpcd 自启动给删了试试, net.xx 可以唤起 dhcpcd 并且分配 ip, 就是不会启动服务, 导致开机时会卡在 dhcp 一小会, 于是又加回来了)

十年前的东西, 依然坚挺!

虽然 udiskie 比较新, 但是 python 是坏文明.

根据后缀和类型用来压缩/解压文件, 有点小bug不过能用. 避免了不同压缩软件的记忆各种命令 (虽然本来也是现用现查的).

笔记本电源管理, 安装好了 rc-update add tlp default 一下, set and forgot.

  • find: fzf, fd
  • grep: ripgrep, sig
  • du: dua
  • df: duf
  • wget: wget2
  • cat: bat
  • ls: eza
  • sed: sd
  • awk & cut: choose
  • ping: gping
  • wget: wget2
  • ps: procs
  • diff: delta
  • curl: curlie

整个图形界面打算只用 Wayland 而不用 X. 使用 WM 而不是 DE.

先试试 tui 的 greet.

openrc 还需要安装 display-manager 然后启用 rc-update add display-manager default

然后配置 /etc/conf.d/display-manager

CHECKVT=7
DISPLAYMANAGER="greetd"

即在 tty7 上启动 greetd.

WM 选择的是 Hyprland, 平铺窗口管理器, 原生支持 Wayland, 看描述还有动画什么的, 感觉还不错 (除了有个 unstable 的 tag).

不是很懂, 为什么还得装好几个版本的 LLVM 以及又要把 python12 给装上来()

懂了我的 ACCEPT_KEYWORDS~amd64, 所以老是要我装 python12. 装就装吧 (因为改回 stable 的 amd64 貌似依赖冲突了, 而且还多装一个 ruby)

LLVM 不知道是哪个包带的, 可以在 USE-llvm.

除了 hyprland 外, 还要装 xdg-desktop-portl-hyprland, 用于不同窗口的通信, 比如屏幕共享, 录制等. 这里会有一个 qt 的依赖链导致一个库需要 USE X, 不过不会装 Xorg. (可是 qt 只有 USE wayland 没有 X, 不懂为什么)

装不起来. 今天是 2023 年 11 月 22 日, 2023-11-21 17:16:31 UTC 有人提了 bug. 等修, 搁置咯.

好快的修, 但是 dev. 而 github 镜像上没有 dev 分支, 于是跑去下了对应 commit 的 snapshot, 替换一下原来的.

(两天后合并到 master 了)

UPD: xdg-desktop-portl-hyprland 需要 qtwayland5, 但是我都用 qt6 编译的软件, 换 xdg-desktop-portl-wlr 了 UPD: 更新了, xdph 可以用 qt6 了, 又换回来了.

还需要启动 elogind, 否则会报没有 XDG_RUNTIME_DIR. rc-update add elogind boot 即可

技巧
elogind 提供了非 root 用户对关机重启等的权限, 使用 loginctl 命令

根据 Hyprland 官网 must have, 还得装通知守护进程, 看了看打算先试试 dunst, 高度定制. 不喜欢 swaync 直接整个右侧弹窗, 而且基于 GTK, 不考虑了, mako 的默认样式也挺简洁, 不过 GTK.

还有个 Tiramisu, 输出到 STDOUT, 可以自己配置, 比如放到 topbar 上. 也挺想玩. 先搞上 dunst, 之后再试试 Tiramisu

dunst 需要一些库支持 X 可以理解, 本身就是 X 下的, 只是后来支持 wayland, 但是需要 w3m 是为什么, 通知网页吗?

(破案了, 某个库需要 w3m build text 支持, 但是实际上没有运行时依赖)

dunst 启动失败, 换 Tiramisu

还是失败, 找了一下原因是没有启动 dbus session. systemd 会自动启动, 直接 Hyprland 就行, 而 openrc 要手动启动, 要用 dbus-run-session Hyprland 包装一下.

是不是 dunst 失败也是这个原因 qaq.

dunst 也 GTK 没发现, 最后用的 fnott.

发现 Hyprland 直接就有 notify, 不知道能不能用这个搞搞, 再说.

不装, 直接在 polkit 里设置管理组都有权限就行. 目前就遇到 OBS 开虚拟摄像头的时候会有这个要求, 其他在终端里的直接手动 doas.

以及配置了一下 doas 不需要密码, 方便多了.

看了一圈好多都是 GTK 的. 比如 Waybar, eww. eww 看起来挺棒的, 而且 writen in rust, 可惜 gtk. 看了一圈大概候选就只有 Yambar.

Yambar 的 ebuild 默认启动了几乎所有 USE flag, 按照需要调整一下, 我关了 i3, dwl, river (这是三个 WM), 以及 mpd (Music Player Daemon, 不打算在 bar 上放什么播放器控制之类的). 其他模块如网络, 电池, cpu 什么的都装上.

yambar 实在是… 一言难尽, 不过作为唯一一个用的有总比没有好

也可能是我艺术细菌太少, 不知道怎么合理运用, 画出好看的 bar. 翻 unixporn 别人配置的确实还不错.

位置会随着内容变化, 暂时在配置文件里用 condition 强行补字符搞成了等长 ("100%", "90% ", "05% " 这种, 有空直接改源码的 fmt, 看了一下代码不复杂, 应该能瞎搞)

只需要最简单的功能, wbg 就合适, 并且压了一个 webp, 减小内存

fuzzel, 小而强大

本来 kitty 里直接有, 但是换成 foot 了就没了. 以及想起来可能有些软件需要系统的图片查看器来查看图片, 所以还是得装个, 不能只有 terminal 里的.

看了一圈 imv 不错.

mpv 启动!

slurp 获取屏幕范围 + grim 截图, 不如 gnome 下的那个截图工具好用. 尤其是 slurp 不能修改选区

找到个 watershot 能够修改选取, 整体还是不如 gnome 下的好用. 暂时先用着.

另外一些集成功能更多的要 gtk.

录屏 OBS 启动!

不需要太多功能, 对比看了一圈, 感觉 Alacritty 挺合适. 然后换成了更轻的 foot, 结果由于 zsh-autocomplet 打字的时候会闪, 又换成了 Kitty, 打字不闪了, 删除的时候会闪了. 不知道到底是谁的问题.

(怎么某 Wrap 还带 AI 的)

换回 foot 了, C/S 架构是真不错

foot 没有标签页, 除了 screen 和 tmux 找到了 zellij 这个 multiplexer, 看上去很现代化, 也能配很多东西. 配合 zjstatus 插件用着感觉不错. 按键也配置成了 vim-like, 并且和 qutebrowser 一样配置了按键直通来处理 Ese.

就是 zellij 不支持 Shift 控制, 这里用了一个小技巧, TODO.

用的 AstroNvim, 就是距离完全配置好还有很大一截, 先暂时能用着.

暂时用的 heh, 没找到更合适的.

其实感觉不如 htop 符合胃口, 但是配置了一翻下来也还行.

本来想直接 vivaldi 的, 即使要装 GTK. 但是, 运行 GTK 程序后鼠标指针变老大, 而且没找到怎么调, wiki 里一堆环境变量也没搞明白().

然后回滚了一下, 找到了一个更 hacker 的浏览器 qutebrowser, 基于 chromium 和 qt6, 键盘驱动. 这下又可以不用 gtk 了. qutebrowser 暂时还不支持 chrome 插件, 不过可以加载 py 和 js, 达到插件的功能. 虽然不强大, 但是日常需求还是可以满足的, 官方有 bitwarden, 太棒了.

最后还是手动改了个插件.

由于老电脑使用的是 zsh, 启动比较慢, 尤其是 pwd 在 git 仓库的时候. 想着换成 fish 会不会好一点. 了解了一下 fish 不支持 bash 语法, 随放弃. 回到 zsh.

zsh 慢不是 shell 本身的原因, 而是我用的插件管理 omz 的锅. 打算用 zinit 了.

zinit 配置是真不友好. 一开始 zsh-completions 和 zsh-autosuggestion 还冲突了, 导致按 tab 补全的时候会把 suggestion 内容也给补上去. 没搞明白, 对着 zinit 文档一抄, 修好了.

ibus 是 gtk 的, 所以只能用 fcitx 了. (有趣的是之前 Ubuntu 想试试 fcitx 结果没成功, 不知道为什么)

fcitx-rime 估计 ebuild 写的也不对, 要依赖 gtk, 遂放弃, 直接使用 fcitx-chinese-addons. 说实话其实没有用到什么 rime 的高级功能, 连候选符号什么的都被我化繁为简了.

就是 fcitx 的皮肤貌似有点难搞. 没搞起来圆角和阴影. 暂时自己随便糊了一个.

sioyek, 一直在用的一个, 键盘驱动, 非常好用. 不过 guru 的 sioyek ebuild 写的不是很对, 于是自己写了一个, 顺便建了一个自己的 overlay. 以后要改什么都可以自己动手. (什么时候 PR 一下)

就是很久不 release, dev 版的更新太勤快了, 今天解决了一个 bug 明天引入了另一个 bug, 受不了, 暂时能用.

UPD: 直接搞了一个 dev 的 USE Flag, 用 dev 的.

暂时不用 gui 的. 找了半天 tui 的, 既要带预览又要方便操作, 同时还不想要太多配置, 还想要轻量好用好看, 有点难. nnn 需要一顿配置才能带预览, ranger 是 python 写的直接跳过, mc 太上世纪了. xplr 不错, 就是用起来很废脑子, 太 hacker 了. 最后找到相对小众一点的 joshuto, 感觉不错. 暂时没配图片预览.

UPD: 换成 yazi 了, 还写了点预览插件用. zellij 的 sixel 好像实现的有问题, 导致 yazi 的预览不太正常. 目前用的 ueberzugpp 预览, 但是无法识别 zellij 的标签, 如果在另一个标签页里有 yazi 的预览, ueberzugpp 窗口还是会开在那儿.

手机上用的是 SagerNet, 可以用 naive. 正巧我服务器上部署的是 naive, 于是想试试在电脑上怎么搞个一样的.

SagerNet 实际上是 sing-box 的 Android 图形前端, 所以要装的是 sing-box. 不过 sing-box 出站不支持 naive, 所以其实还是得使用 naive 客户端. 其实 Android 上的也是要多装一个插件的.

正巧之前搞了个 overlay, 就想着看看 naive 怎么编译, 翻了一下代码被震惊了, naive 是用 chromium 的代码编译来的. 原来了解过 naive 是用的 chromium 协议栈, 但是没想到是这样 “用”.

然后 github build workflow 看不懂, 索性写了个 naiveproxy-bin 的 ebuild.

又想了想, 老电脑上 thunderbird 代理挂不上, qutebrowser 不支持插件, 没有 switch omega, 而且不同程序对环境变量 socks 协议的标识还可能不一样 (比如有些不认 socks5:// 只认 socks5h://, 有些又反过来), 那么日常使用代理着实有点麻烦. 于是想到能不能用 sing-box 的 TUN 模式直接搞透明代理, 顺便把分流也给配置了, 问题直接全部解决, 皆大欢喜.

然后痛苦就开始了.

首先 sing-box 是 go 写的, 这玩意手动编译只需要一句话, 自动给下载依赖什么的, 但是 ebuild 认为你在编译的时候不能乱下东西, 查了老半天才搞明白要怎么弄.

我的想法入站 TUN, 出站 socks (naive), 但是这样会导致经典的路由环, 流量永远出不去. 找到个 sing-box 在 windows 下的 TUN 配置示例, 在配置文件中 TUN 入站排除了 v2ray 和 xray. 照猫画虎, 写个 naive. 但是实际上并没有按照我想的方式运行, 可能是一些请求并不是从 naive 出来的.

然后去搜了一些解决方案, 包括改路由表什么的. 比如把目的 ip 是代理服务器的包给走真正的网卡, 其他包都走 TUN. 这样弊端也很明显, 就是换了 ip 的话还需要修改. 正当我发愁的时候, 仔仔细细翻 sing-box 文档, 终于给翻出解决方案了: 入站可以排除某个用户的!

反正 naive 也不在公开可用的 overlay 中, 于是自己写一个 rc service, 并且带了一个 naive 用户 (组) 执行, 然后 sing-box 用另一个用户 (组) 执行 service, 并将这两个 service 都添加到开机启动, 成功解决!

看了一下路由表, 其实修改的是根据用户 (uid) 来走不同路的. 不知道为啥搜不到这种解决方式, 我觉得很优雅啊.

打 pwn 的没有 ida 还是有点难受, 还是有必要搞个 wine 的. 把一切不必要的 USE 全去了, 并且留额外加一个 wow64, 可以不按照 32 位库 (各种库重新编译一个 32 位的着实有点慢), 装好了结果图形界面打不开, 一会说没有图形驱动一会说没有 X, 而且没法稳定复现. 查了一圈有说 wine 可以支持 wayland (测试), 也设置了 wayland USE, 就是不行. 经过一系列重装 wine 都以失败告终, 最后发现一个 wine-wayland 的仓库, 然后去搜了一下 overlay, 还真有个不在 gentoo 和 guru overlay 中的包.

编译了一下发现失败了, 查了一会发现是 libxkbcommon 这个库更新了, 删除了一些常量, 而代码并没有适配. 又到了自己动手丰衣足食环节! 在 github 的 wine-wayland 仓库找了一圈没找到源码, 一看 ebuild, 原来是 wine 仓库的 wayland 分支.

麻了, 那 wine 的 wayland USE 是干嘛的…

打上 patch 后终于成功了.

UPD: 试了一下 9+ 原版的 wayland 驱动, 用 ida 的时候他把下拉菜单当成一个窗口处理了, 不如 wine-wayland.

看了一圈, 还是 thunderbird 好, 但是我这 status bar 没 tray, 于是放弃. 搜了一下 TUI 的, 用了 neomutt.

用 mutt-wizard 配好了 gmail 和 xdu 邮箱的 (你电的邮箱真的搞人, 又不告诉你正确的 imap 地址又不能用 ssl) imap, stmp 还没试过.

邮件这一套是真分工合作, 刷新了我的认知. 收邮件, 存邮件, 管理邮件, 看邮件, 发邮件都是不一样的软件. 首先 isync 拉邮件到本地, 本地是个 mailbox 格式存的邮件仓库, 然后 notmuch 管理邮件, neomutt 查看邮件, 还有个发管邮件叫啥一下子忘了…

用 goimapnotify 配了各 imap 收到邮件的通知, 感觉还是有点 bug. 打算换成 hap 查看本地邮箱更新状态, 然后定时拉取邮件. hap 居然没找到文档什么的, 搁置一下.

gmail 好像屏蔽了我的新 vps, goimapnotify 收不到了. 再看看有没有其他解决方法.

UPD: 发现 gmail 的 imap 可以直连, 把 sing-box 里设置了 imap 开头的域名直连, 解决了. 并且设想开机自动对每个邮箱执行一次 mbsync + notmuch new, 就知道有没有新邮件了.

UPD: goimapnotify 的 bug 也调出来了, 貌似是 google imap server 的问题, 他连上一段时间内是可以正常收到推送的, 一段时间之后 (我也不知道多少没测, 可能不到 10min), 即使一直保持连接, 服务器也不会推送. 简单的方法是重新连接(重新发送 IDEL 数据包), 自己改了改代码写了个 poc 能行, 给作者提 feature request 了还没回. 以及有 sb 贴日志的时候不小心把密码贴出去了, 幸好小众项目没什么人看到.

配 imap 和 stmp 要用到密码, gpg 开机自动化没搞成, 暂时存的明文. (这就导致 dotfiles 没法公开qaq)

UPD: 配完了很简单, 对着 pam-gnupg 的 readme 就行.

管理 wayland 的剪切板, 看了一圈也就 cliphist 还活着. 结合 fuzzel 还挺好用.

bitwarden 用户, bitwarden 有自己的 cli, 但是不太好用. 找到个第三方的 rbw, 非常好第三方. 暂时不支持根据 uri 找用户名和密码, 有人提了 PR, 并且带了 qutebrowser 的脚本, 好像因为代码质量还没合并. 自己先打上了, 并且改了改 qutebrowser 的脚本, 虽然还有点问题不过能正常用着.

UPD: uri 合并了.

bluetuith, 这 tui 真好看吧.

对比了一下感觉 chezmoi 蛮好用. 就是没有 overlay, 自己搞了一个.

有点想使用 Android, 毕竟 qq 微信什么的还是不方便 (不考虑electron这种臃肿的垃圾了). 看了一下 Waydroid 容器解决方案, 不过看上去兼容性不一定好. 于是还是用 scrcpy 投屏吧.

想要 cli 或者 tui 的, 支持显示多种进制, 就像 rz-ax 那样. 但是 rz-ax 直接用起来还是不太方便, 无法小数计算. 最近找到了 fend, 虽然没有把进制都给出来, 但是可以自己转换, 先用着.

pwn 人还需要一点 pwn 需要的工具.

找到个 pwninit, 用来一键 patchelf. 自己动手修改了一点, 索性 fork 了一份改了个名.

gdb 需要改一下 USE Flag, xml 得有, 不然调 qemu 连远程会寄. 然后还有个 multitarget, 直接支持多架构, 不需要装 gdb-multiarch 之类的, 非常爽.

pwndbg 和 gef 在官方 overlay 里有维护, 还挺方便, 以及他还包装了一下命令, 可以和原版 gdb 分开运行. 赞!

问题又来了, pwntools 的 gdb 功能只会启动 gdb, 而不能找 gdb-gef 或者 pwndbg 这种. 找了一圈发现优先看有没有 pwntools-gdb, 有的话启动这个. 于是做了个简单的 eselect, 去切换 pwntools-gdb 软链接.

(还可以写个脚本, 这样就可以用 rizin 调试了)

这两是一个人写的, 而且用的 ruby. 暂时没有 overlay 包含了这俩, 于是学了几天的 ruby gem 打包, 整了几天的依赖问题, 最终给解决了.

怎么有人循环依赖这么大的事解决了不发个 release, 找了一万年, 还以为是我 ebuild 写的有问题.

自己打包一个.

rz-ghidra 有人打包了, 直接用

得 USE Flag 加上 python 才会装 python 的库.

可以直接用

找了个 crack 的, 维护了个私人 overlay 自己用嘻嘻.

UPD: 老 vps 跑路了没备份 overlay 寄了.

wireshark 可以无 gui (虽然好像其实也有 qt6 的) 抓流量包, 或者 tcpdump. 然后查看流量包可以用 termshark, 但是不太会用 (wtb 的时候看没找到怎么看具体流量拖后腿qaq)

受够了之前 rootless 跑不了 redpwn/jail, 这回不配 rootless 了. 同时把常用用户加进 docker 组里, 这样不用每次都 sudo.

管理的话从 dry 换到 lazydocker.

还有一个大问题, 由于 glibc 等依赖是根据 CPU 支持的指令集优化编译的, 静态编译出的程序带了这些指令, 导致在 qemu 或者远程中没法跑. 而 gentoo 又不支持同时安装 musl-gcc. 想了个办法, 在 docker 中编译. 使用 docker 官方 gcc 环境, 加自己装一个 musl-tools, 这样就有 glibc 和 musl 可以用了. 还可以写个简单的函数来化简命令:

1
2
3
function build_universal() {
    docker run --rm -v "$PWD":/codes -w /codes wingszeng/gcc "$@"
}

字体用 Noto + Ubuntu Nerd Font, 还是会缺一点 unicode, 不知道为什么

鼠标指针 Bibata Classic

配色 monokai soda

dark2 = "#111111",
dark1 = "#1a1a1a",
background = "#222222",
text = "#f8f8f2",
accent1 = "#f92672",
accent2 = "#fd971f",
accent3 = "#e6db74",
accent4 = "#a6e22e",
accent5 = "#66d9ef",
accent6 = "#ae81ff",
dimmed1 = "#a2a2a2",
dimmed2 = "#888888",
dimmed3 = "#6f6f6f",
dimmed4 = "#555555",
dimmed5 = "#3c3c3c",

(屏幕颜色没校过, 貌似饱和度过高, 看着有点难受)

窗口样式无边框, 阴影, 圆角大概 16px.

QT 主题用 qt6ct 配置, 但是他好像颜色其实有点不太对? 随便先搞个 dark 的用着.