macOS 和 Linux 用久了有点审美疲劳,尝试下用 BSD 作桌面系统,目标是能用 Firefox 或者 Chrome Web 浏览器成功播放 https://douban.fm 的音乐,能正常显示中文,能正常输入中文,并使用 MacBook Pro 的高分辨率显示屏。

使用 macOS Mojave 10.14.2 上运行的 VirtualBox 5.2.22 作为虚拟机,分配两个 CPU,Audio Controller 为 “Intel HD Audio”,128MB Video memory,开启 HiDPI support。

NetBSD

安装程序非常易用,使用 https://mirrors4.tuna.tsinghua.edu.cn/ 上的 pkgsrc 镜像,下载速度飞快,安装完后的起步文档:

软件包管理:pkgsrc,pkg_install 和 pkgin。

pkgin install mksh bash fish    # 默认的 ksh 在 xterm 里中文宽度和位置判断有问题
chsh -s /usr/pkg/bin/fish       # 针对普通用户,需要 logout 再 login 生效

pkgin install dejavu-ttf noto-ttf
pkgin install firefox52     # 最后一个不依赖 Rust 的 Firefox 版本
pkgin install fcitx fcitx-configtool adwaita-icon-theme
pkgin install xdg-utils
mkdir -p /usr/local/bin
ln -s /usr/pkg/bin/firefox52 /usr/local/bin/firefox

NetBSD 默认使用 xdm 启动 X server,不用 startx + xinit,所以配置 $HOME/.xinitrc 是无效的,需要配置 $HOME/.xsession,参考 /etc/X11/xdm/Xsession 以及 Fcitx 官方文档

## ~/.xsession

export LANG=en_US.UTF-8
export LC_CTYPE=zh_CN.UTF-8
export XMODIFIERS=@im=fcitx
export GTK_IM_MODULE=fcitx
export QT_IM_MODULE=fcitx

resources=$HOME/.Xresources
[ -r "$resources" ] && /usr/X11R7/bin/xrdb -load "$resources"

/usr/pkg/bin/fcitx-autostart
for i in 1 2 3 4 5; do
    echo waiting for fcitx...
    sleep 1
    /usr/pkg/bin/fcitx-remote >/dev/null 2>&1 && break
done

exec /usr/X11R7/bin/xsm

给 xterm 设置一些基本参数,另两个强大的轻量级终端模拟器 rxvt-unicode 和 mlterm 很值得试试。NetBSD 预先编译的软件包有些问题,比如 mlterm 启动不了,vim-gtk3 也启动不了,基础系统的 /usr/X11R7/bin/xterm 不支持 smaller-vt-font() 和 larger-vt-font(),需要在 /usr/pkgsrc/x11/xterm 下 make install 安装一份新的。

! ~/.Xresources

! See https://www.freedesktop.org/software/fontconfig/fontconfig-user.html
Xft.antialias: 1
Xft.autohint: 0
! set to 120, 144, 168 or 192 for HiDPI screen
Xft.dpi: 96
Xft.hinting: 1
Xft.hintstyle: hintslight
Xft.lcdfilter: lcddefault
Xft.rgba: rgb

XTerm*loginShell: true
XTerm*termName: xterm-256color
XTerm*saveLines: 1024
XTerm*selectToClipboard: true
XTerm*vt100.translations: #override \n\
    Ctrl Shift <Key> C: copy-selection(CLIPBOARD) \n\
    Ctrl Shift <Key> V: insert-selection(CLIPBOARD) \n\
    ~Shift <Btn1Up>: select-end(PRIMARY, CLIPBOARD, CUT_BUFFER0) \n\
    Shift <Btn1Up>: exec-selectable("xdg-open '%t'", word) \n\
    Shift <KeyPress> Up: scroll-back(1, page) \n\
    Shift <KeyPress> Down: scroll-forw(1, page) \n\
    Ctrl <Key> minus: smaller-vt-font() \n\
    Ctrl <Key> plus: larger-vt-font() \n\
    Ctrl <Key> 0: set-vt-font(d)
XTerm*cjkWidth: false
XTerm*faceName: DejaVu Sans Mono:style=Book:antialias=true
XTerm*faceNameDoublesize: Noto Sans Mono CJK SC:style=Regular
XTerm*faceSize: 12
XTerm*faceSize1: 8
XTerm*faceSize2: 10
XTerm*faceSize3: 12
XTerm*faceSize4: 14
XTerm*faceSize5: 16
XTerm*faceSize6: 22
XTerm*renderFont: true
XTerm*scaleHeight: 1.01
XTerm*charClass: 33:48,36-47:48,58-59:48,61:48,63-64:48,95:48,126:48
XTerm*scrollBar: true
XTerm*scrollKey: true
XTerm*rightScrollBar: true
XTerm*scrollTtyOutput: false
XTerm*highlightSelection: true
XTerm*trimSelection: true

参考 https://www.tumfatig.net/20190131/customized-resolution-for-openbsd-in-virtualbox/ 使用 VESA 1600x1200 分辨率,没搞定 Retina 屏的 2880x1800 分辨率。由于 1600x1200 是 VESA 内置模式,因此并不需要用 VBoxManage 命令设置一个自定义分辨率。使用 VirtualBox 的 View -> Scale Factor -> 150%,能占据 Retina 屏大部分区域,但是大概是缩放的原因,运行非常缓慢。

# /etc/X11/xorg.conf.d/00-virtualbox.conf

Section "Device"
  Identifier   "VirtualBox-Card"
  Driver       "vesa"
  VendorName   "InnoTek"
  BoardName    "VirtualBox Graphics Adapter"
EndSection
Section "Monitor"
  Identifier   "VirtualBox-Monitor"
  VendorName   "InnoTek"
  ModelName    "VirtualBox Screen"
  HorizSync    1.0 - 1000.0
  VertRefresh  1.0 - 1000.0
EndSection
Section "Screen"
  Identifier   "VirtualBox-Screen"
  Device       "VirtualBox-Card"
  Monitor      "VirtualBox-Monitor"
  DefaultDepth 24
  SubSection   "Display"
    Viewport   0 0
    Depth      24
    Modes      "1600x1200"
  EndSubSection
EndSection

OpenBSD

OpenBSD 的安装程序没那么 user-friendly,尤其吐槽的是自动分区分的特别细碎,我只是试用,所以把根分区和swap分区之外的分区全删除了,把空出来的磁盘全部分配给了根分区。对 Xenodm 选择 yes。安装完成后进入系统,以 root 账户执行 syspatch 打上补丁(如果 syspatch 更新了自己,会提示再执行一次)。

修改 /etc/installurl,使用 https://mirrors4.tuna.tsinghua.edu.cn/OpenBSD

pkg_info -Q fcitx
pkg_info -Q chrom
pkg_info -Q firefox

pkg_add fcitx fcitx-gtk3 fcitx-qt4 fcitx-qt5
pkg_add firefox chromium noto-fonts noto-cjk

pkg_add bash fish                   # 默认的 ksh 在 xterm 里中文宽度和位置判断有问题
chsh -s /usr/local/bin/fish         # 针对普通用户,需要 logout 再 login 生效

OpenBSD 使用 Xenodm 显示管理器,跟 XDM 非常像,同样使用 ~/.xsession~/.Xresources 来定制。

## ~/.xsession

export LANG=en_US.UTF-8
export LC_CTYPE=zh_CN.UTF-8
export XMODIFIERS=@im=fcitx
export GTK_IM_MODULE=fcitx
export QT_IM_MODULE=fcitx

resources=$HOME/.Xresources
[ -r "$resources" ] && /usr/X11R6/bin/xrdb -load "$resources"

/usr/local/bin/fcitx-autostart
for i in 1 2 3 4 5; do
    echo waiting for fcitx...
    sleep 1
    /usr/local/bin/fcitx-remote >/dev/null 2>&1 && break
done

/usr/X11R6/bin/xterm &
exec /usr/X11R6/bin/fvwm

~/.Xresources 内容和 NetBSD 的版本一样。使用 1600x1200 分辨率的方式同 NetBSD。

DragonFlyBSD

DragonFlyBSD 派生自 FreeBSD,所以在 VirtualBox 里创建 FreeBSD 64bit 类型的虚拟机。

修改 /usr/local/etc/pkg/repos/df-latest.conf 将 Avalon 的 enabled 改成 no,新建文件 /usr/local/etc/pkg/repos/koddos.conf:

Koddos {
        url         : https://mirror-hk.koddos.net/dragonflybsd/dports/${ABI}/LATEST,
        enabled     : yes
}

FreeBSD 和 DragonFlyBSD 都使用 pkg 命令管理二进制软件包。

pkg update

pkg install xorg xdm

DragonFlyBSD 的官方文档很少,也很短,有三篇跟桌面相关:

  1. https://www.dragonflybsd.org/docs/handbook/X/
  2. https://www.dragonflybsd.org/docs/how_to_get_to_the_desktop/
  3. https://panoramacircle.com/2018/10/07/setup-dragonflybsd-with-a-desktop-on-real-hardware-thinkpad-t410/
# 允许指定用户使用 3D 加速
pw groupmod video -m YOUR-FIRST-NON-ROOT-USER

pkg install dejavu noto
pkg install zh-fcitx zh-fcitx-configtool zh-fcitx-libpinyin fcitx-qt5
pkg install firefox chromium

dbus-uuidgen --ensure=/etc/machine-id   # fcitx 依赖了 dbus,dbus 依赖这个文件

pkg install mksh bash fish
chsh -s /usr/local/bin/fish         # 针对普通用户,需要 logout 再 login 生效

配置 ~/.xsession:

## ~/.xsession

export LANG=en_US.UTF-8
export LC_CTYPE=zh_CN.UTF-8
export XMODIFIERS=@im=fcitx
export GTK_IM_MODULE=fcitx
export QT_IM_MODULE=fcitx

resources=$HOME/.Xresources
[ -r "$resources" ] && /usr/local/bin/xrdb -load "$resources"

/usr/local/bin/fcitx-remote >/dev/null 2>&1 || /usr/local/bin/fcitx
for i in 1 2 3 4 5; do
    echo waiting for fcitx...
    sleep 1
    /usr/local/bin/fcitx-remote >/dev/null 2>&1 && break
done

/usr/local/bin/xterm &
exec /usr/local/bin/twm

~/.Xresources 内容和 NetBSD 的版本一样。使用 1600x1200 分辨率的方式同 NetBSD。

修改 /boot/loader.conf,加入:

snd_hda_load=”YES”
snd_uaudio_load=”YES”

修改 /etc/rc.conf,加入:

moused_enable="YES"

修改 /etc/ttys 把下面这行中的 off 改成 on,然后重启虚拟机:

ttyv8   "/usr/local/bin/xdm -nodaemon"  xterm   off secure

FreeBSD

四大 BSD 分支里,最流行的 FreeBSD 得天独厚的有 VirtualBox Guest Addition 的支持,基于 FreeBSD 的桌面定制版也是最多的,主要有这四个:

  • PC-BSD -> TrueOS Desktop -> Project Trident: TrueOS 最早从著名的 FreeBSD 桌面发行版 PC-BSD 起家,后来逐渐转向服务端,其产品称为 TrueOS,桌面版本称为 TrueOS Desktop,如今则更进一步,TrueOS 成为各个衍生“三手版”的基石,在此基础上 TrueOS Desktop 变为 Project Trident,GhostBSD 目前也是基于 TrueOS。 (2019 年 Project Trident 转向以 Void Linux 为基础)
  • GhostBSD: 采用 Gnome 2 的后续分支 MATE 桌面环境,在 MacBook Pro 上的 VirtualBox 下运行的很好,MATE 桌面环境做的很精致,除了鼠标移动飘忽不定,伊探测用了 vmware 的鼠标驱动 vmmouse,失败后转去用了 Xorg 自带的鼠标驱动 mouse,手动切换为 vboxmouse 后倒是鼠标不飘了,鼠标点击却失效了。抛开这个缺憾,这大概是基于 FreeBSD 做的最好的桌面系统了。
  • MidnightBSD: 使用自己独有的 mports 软件包。
  • NomadBSD: NomadBSD is a 64bit live system for USB flash drives, based on FreeBSD®
  • FuryBSD: 最新出的轻量级 FreeBSD 桌面版。 (2020 年停止开发)

配置 FreeBSD 桌面的文章:

FreeBSD 在国内的非官方镜像:

安装完 FreeBSD 后的一些后续步骤:

  1. 升级系统

    freebsd-update fetch
    freebsd-update install
    reboot
    

    如果升级后系统无法启动,报告 ZFS i/o error,可以尝试以 FreeBSD 安装 iso 启动,进入 Live 模式:

    mkdir /tmp/altroot
    zpool import -o altroot=/tmp/altroot -N -f zroot
    zfs mount zroot/ROOT/default
    zfs mount -a
    cd /tmp/altroot/boot
    mv kernel kernel.bad
    mv kernel.old kernel
    reboot
    

    另一种更简单但是不一定工作的方式,在启动时按 ESC 进入 boot loader 提示符,输入:

    unload
    load kernel.old
    

    进入系统后将 /boot/kernel.old 恢复成 /boot/kernel,或者使用 freebsd-update rollback 回滚。

  2. 将普通用户加入 wheel 组才能执行 su 命令: pw groupmod wheel -m YOUR-FIRST-NON-ROOT-USER

  3. 设置环境变量 MANWIDTHtty,则 man 命令输出会占满终端窗口;设置环境变量 MANPAGERmost 并安装 most 软件包后可以查看彩色手册页;设置环境变量 CLICOLOR=1ls 显示彩色。

  4. FreeBSD Generic 内核默认使用新的 vt driver,不是老的 sc driver,vt driver 目前不支持 vesa,Handbook 这里描述的 kldload vesa 不工作,解决办法是在 /boot/loader.conf 写入如下配置:

    # 需要使用 EFI 引导系统,1080p 指 1920x1080
    efi_max_resolution="1080p"
    

    在 /etc/rc.conf 写入:

    # 可用字体:/usr/share/vt/fonts/
    allscreens_flags="-f terminus-b32"
    
  5. local_unbound 默认开启了 DNSSEC,一些 ISP 的 DNS 服务器不支持,从而无法解析任何域名,可以使用 drill -S freebsd.org @DNS-SERVER-IP 确认。可以禁止 resolvconf 自动生成 /etc/unbound/forward.conf:

    ## /etc/resolvconf.conf
    
    unbound="NO"
    
    
    ## /etc/unbound/forward.conf
    
    # 对 name: "." 指定固定的 DNS server
    forward-zone:
            name: "."
            forward-addr: 8.8.8.8
    

    执行 service local_unbound reload 让 unbound 重新加载配置。

  6. 更新 ports collection:

    # 使用 host -t srv _http._tcp.portsnap.freebsd.org 8.8.8.8 或者
    # dig @8.8.8.8 _http._tcp.portsnap.freebsd.org srv 检查 portsnap 镜像,
    # 其中 ec2-eu-west-1.portsnap.freebsd.org 和 your-org.portsnap.freebsd.org
    # 速度比较快,但是都不稳定。
    #
    # portsnap.cn.FreeBSD.org 对应的 portsnap.hshh.org 和 portsnap.tw.FreeBSD.org 比较快。
    #
    # 可以直接修改 /etc/portsnap.conf 配置文件
    portsnap -s portsnap.cn.FreeBSD.org auto
    
  7. 在 /etc/make.conf 里设置 ports 的 distfiles 下载镜像:

    ## 需要提前 pkg install axel
    ## 参考:/usr/ports/Mk/bsd.port.mk,注意 make.conf 是 Makefile 语法
    FETCH_CMD=axel -a -n 4
    DISABLE_SIZE=yes
    
    MASTER_SITE_OVERRIDE?=\
      http://mirrors.163.com/freebsd-ports/distfiles/${DIST_SUBDIR}/ \
      http://mirrors.ustc.edu.cn/freebsd-ports/distfiles/${DIST_SUBDIR}/
    
  8. 安装图形界面

    pkg install xorg xdm xsm noto
    pkg install drm-kmod xf86-video-vmware virtualbox-ose-additions
    pkg install fcitx-qt5 zh-fcitx zh-fcitx-configtool zh-fcitx-libpinyin zh-fcitx-sunpinyin
    pkg install chromium firefox
    
    dbus-uuidgen --ensure=/etc/machine-id    # fcitx 依赖了 dbus,dbus 依赖这个文件
    
    pw groupmod video -m SOME_USER
    
    ## 修改 /etc/ttys 将 xdm 所在行的 off 改成 on
    
    ## 根据 xorg-server 包的提示,修改 /etc/sysctl.conf 添加:
    kern.evdev.rcpt_mask=6
    
    ## 根据 virtualbox-ose-additions 包的提示,修改 /etc/rc.conf 添加:
    vboxguest_enable="YES"
    vboxservice_enable="YES"
    
    ## 很多桌面应用依赖 dbus,所以修改 /etc/rc.conf 添加:
    dbus_enable="YES"
    
    ## 启动系统级别的 dbus
    service dbus start
    
    pw groupmod wheel -m SOME_USER  # 支持 virtualbox clipboard sharing, window scaling
    

    使用 xrandr 命令获得获得支持的分辨率,然后写入文件 /usr/local/etc/X11/xorg.conf.d/screen-resolution.conf

    Section "Screen"
        Identifier "Screen0"
        Device     "Card0"
        SubSection "Display"
            Modes      "2880x1620"
        EndSubSection
    EndSection
    

    配置 ~/.xsession:

    #!/bin/sh
    
    export LANG=en_US.UTF-8
    export LC_CTYPE=zh_CN.UTF-8
    export XMODIFIERS=@im=fcitx
    export GTK_IM_MODULE=fcitx
    export QT_IM_MODULE=fcitx
    
    resources=$HOME/.Xresources
    [ -r "$resources" ] && /usr/local/bin/xrdb -load "$resources"
    
    /usr/local/bin/fcitx
    for i in 1 2 3 4 5; do
        echo waiting for fcitx...
        sleep 1
        /usr/local/bin/fcitx-remote >/dev/null 2>&1 && break
    done
    
    exec /usr/local/bin/xsm
    

    ~/.Xresources 内容和 NetBSD 的版本一样。

FreeBSD root on ZFS 千古奇坑

参考 https://forums.freebsd.org/threads/10-1-doesnt-boot-anymore-from-zroot-after-applying-p25.54422/#post-308876 ,FreeBSD 的 root on zfs 对 vdev 有要求,需要对磁盘分区,并设置分区类型为 freebsd-zfs,不能把整块磁盘加入 zpool,虽然 zfs 本身能工作,但是 /boot/loader 不能识别,一旦 freebsd-update install 后 /boot 目录的文件写入了这个整盘构成的 vdev,loader 就会报错 ZFS: i/o error - all block copies unavailable。推荐的配置是构成 root zpool 的所有 vdev 采用相同的分区结构,并且冗余 efi、freebsd-boot、freebsd-swap 分区,以使得任何一块盘坏掉了,还可以用其它盘成功启动。

给 zroot 增加第二块盘:

gpart destroy -F ada1               # optional for new disk
zpool labelclear -f /dev/ada1       # optional for new disk

gpart create -s gpt ada1

## For UEFI Boot:
gpart add -a 4k -l efiboot1 -t efi -s 200M ada1
gpart bootcode -p /boot/boot1.efifat -i 1 ada1  # 写入第一个分区
    ### boot1.efifat 等价于:
    # newfs_msdos -F 16 -L EFISYS /dev/ada1p1
    # mount -t msdosfs /dev/ada1p1 /mnt
    # mkdir -p /mnt/efi/boot
    # cp /boot/loader.efi /mnt/efi/boot/BOOTx64.efi
    # echo BOOTx64.efi > /mnt/efi/boot/startup.nsh
    # umount /mnt

## For Legacy Boot:
gpart add -a 4k -l gptboot1 -t freebsd-boot -s 512K ada1
gpart bootcode -b /boot/pmbr -p /boot/gptzfsboot -i 2 ada1  # 写入第二个分区

## For swap and data:
gpart add -a 1m -l swap1 -t freebsd-swap -s 2G ada1
gpart add -a 1m -l zfs1 -t freebsd-zfs ada1
zpool labelclear -f /dev/ada1p3     # optional for new disk
zpool labelclear -f /dev/ada1p4     # optional for new disk

zpool add zroot /dev/ada1p4