洋洋洒洒写了一大堆,最后还不是什么都往 /opt 丢

手法介绍

这个方案大致的思路就是通过拉取所需系统的镜像建立一个特别的容器,然后使它与主机互通网络、设备、图形接口、home 目录等等。这样,在容器内安装的软件可以在主机无缝使用,同时又不搞乱主机系统文件。

建立这样一个特别的容器需要好多操作,幸运的是已经有人把指令包装好了。这里将介绍的是 distrobox 方案。

首先,一切的一切,你需要一个容器运行时。可选的有 Docker 社区版和 Podman 。我这里选择的是 Podman ,因为我不想开机就有 docker 守护进程在后台跳舞。对于大多数发行版,直接安装即可:

# apt install podman
# pacman -S podman
# zypper in podman
# dnf install podman
...

这样就能用了。如果是 arch 用户,安装完之后只有 root 能运行容器,你还需要按照 wiki 说明配置为 rootless 模式。

之后安装 distrobox 。目前只有 openSUSE 、Debian Sid 、Fedora 打了包 (哦哦,还有 AUR) 。这里以 openSUSE 为例:

# zypper in distrobox

如果你使用的发行版没有打包,那么需要按照 readme 里的说明手动安装。这里是个示例:

$ curl -s https://raw.githubusercontent.com/89luca89/distrobox/main/install | sudo sh

完成后,就能直接创建我们想要的发行版容器了。我这里选择了 archlinux ,因为作为一个社区驱动的发行版,我就没见过不能在 arch 上跑的软件。

$ distrobox create --name arch --image archlinux

执行这一步操作,distrobox 会从 docker hub 上拉取 archlinux:latest 镜像,然后创建对应的容器,并命名为 arch 。执行成功后会输出下一步操作的指令:

$ distrobox enter arch

这一步完成后对应的终端就会显示容器里的命令行输出了。不过事情通常不会那么简单…… distrobox enter 的操作会自动执行系统更新的命令,而镜像内默认的软件源很可能在地球的另一端之类,这一步将会进行得相当缓慢。最简单的处理方法是 泡杯茶硬等 挂代理,如果手上没有趁手的互联网直通车的话你可以提前进入容器内修改软件源列表。

$ podman start arch
$ podman exec -it arch bash

这里的 arch 是别名,也可以用执行 distrobox list 后列出来的那个 ID 。进入容器后还有另一个问题,这类镜像通常极为精简,所以压根就没有编辑器供你使用。所以你可能得把软件源列表文件删了然后用 echo 大法:

sudo echo "Server = https://mirrors.tuna.tsinghua.edu.cn/archlinux/\$repo/os/\$arch" >> /etc/pacman.d/mirrorlist

或者 sed 替换大法之类……总之想办法更新软件源列表,然后再执行 distrobox stop archdistrobox enter arch

顺利的话,你已经进入一个可以为所欲为的容器了。你可以装任何你想装的软件,然后直接从命令行唤出,就像这本来就是主机系统一样。你也可以直接导出各种启动方式到主机,譬如导出到 desktop 文件:

$ distrobox-export --app software_name

然后在桌面启动器里就能看到启动图标了。要注意,导出命令是在容器内执行的。

日常维护

好了,这下我们兜兜转转又跑起了 arch ,这不是又回到了天天滚系统的日子?

其实并不需要。首先,容器里的软件包不会太多,系统依赖关系更简单,不容易挂。其次,我们想要的只是打包好的软件包而已,所以并不需要担心系统滚挂的问题。就算挂了又如何,删了重建就是了。我们只需要导出软件列表:

$ pacman -Qqe > pkglist.txt

当然还有 AUR 等外部来源的软件包列表:

$ pacman -Qqem > foreignpkglist.txt

如果真滚出麻烦,照着列表再装一遍就是。

此外,容器可以不止一个。你完全可以把特殊的软件隔离开,只是多占点磁盘空间罢了。用 Linux 这些年,没少装奇奇怪怪的软件,经常把系统搞到脏兮兮的。放到容器里装,就像垫上一张餐桌布一样。不过需要注意的是,默认情况下,你的 home 目录也是暴露给容器内的。

可能出现的问题及解决方法

1.添加 archlinuxcn 源后导入 GPG keyring 报错。

执行以下操作:

sudo rm -rf /etc/pacman.d/gnupg
sudo pacman-key --init
sudo pacman-key --populate

然后安装 keyring:

sudo pacman -Sy archlinuxcn-keyring

2.使用 AUR helper (yay, paru …) 时显示 ==> ERROR: Cannot find the strip binary required for object file stripping.

安装 binutils 即可:

sudo pacman -S binutils

以此为原型的发行版

发散一下思维,能不能让所有软件都安装在容器里?

当然可以。甚至还能更进一步,让主机系统的绝大部分变成只读,让系统变得绝对稳定可靠,可以各版本间自由来回滚动。

现在较为知名的桌面方案是 Fedora Silverblue 以及 openSUSE MicroOS ,还有 Fedora IoT 作为 Official Edition 推出。

在任意 Linux 发行版安装 ROS

这是额外的独立章节,介绍在任意发行版上安装对发行版有特殊限定的软件包/软件集。以机器人操作系统为例,提供给有需要的人。毕竟咱曾经用 ROS 骗过大创经费

方案一

首先使用包管理器安装 Podman 和 distrobox 。若没有提供 distrobox ,按照此链接说明安装。

完成后,开始创建安装 ROS 所需的容器。我这里选择 Ubuntu 22.04 LTS (ROS 官方品质之选,毕竟支持时间长)以及 ROS2 Humble Hawksbill 。

首先拉取 Ubuntu 22.04 LTS 镜像,并创建容器:

$ distrobox -n ros2.humble -i ubuntu:22.04

完成后进入容器命令行环境:

$ distrobox enter ros2.humble

第一次进入需要一些时间,但通常不会很慢。默认使用官方的源大概有 CDN ,金钱的力量 你可以通过 podman logs -f ros2.humble 查看具体输出。

进入后第一步,先顺手再更新一下系统:

$ sudo apt update
$ sudo apt upgrade

然后按照 ROS 官方文档添加软件源。因为语言环境通常默认是 UTF-8,universe 储存库默认也已添加,我们就跳过这两步。首先下载添加 ROS 官方的 GPG key :

$ sudo apt install curl gnupg gnupg2 lsb-release
$ sudo curl -sSL https://raw.githubusercontent.com/ros/rosdistro/master/ros.key -o /usr/share/keyrings/ros-archive-keyring.gpg

然后添加官方软件源列表:

$ echo "deb [arch=$(dpkg --print-architecture) signed-by=/usr/share/keyrings/ros-archive-keyring.gpg] http://packages.ros.org/ros2/ub
untu $(source /etc/os-release && echo $UBUNTU_CODENAME) main" | sudo tee /etc/apt/sources.list.d/ros2.list > /dev/null

我这里使用的是 tuna 的镜像源:

$ echo "deb [arch=$(dpkg --print-architecture) signed-by=/usr/share/keyrings/ros-archive-keyring.gpg] https://mirrors.tuna.tsinghua.e
du.cn/ros2/ubuntu jammy main" | sudo tee /etc/apt/sources.list.d/ros2.list > /dev/null

然后就可以开始安装 ROS 的软件包了。先更新本地源:

$ sudo apt update

然后直接安装 ROS 完整桌面软件集:

$ sudo apt install ros-humble-desktop

Apt 会自动处理依赖。你需要准备 3~4G 的磁盘空间,然后等待安装完毕。

完成后,配置一下环境,就可以使用了。

方案二

实际上 docker hub 上有现成的 ROS 镜像可供使用,由 OSRF 直接维护。你直接拉取下来就行:

$ podman pull osrf/ros:humble-desktop-full-jammy

冒号后的标签你可以自由选择。

方案三

有没有可以远程的方案?

有的。请看这个。你可以通过浏览器远程访问容器内的桌面,然后像处理虚拟机一样处理容器实例,但磁盘占用和性能损失比虚拟机方案小很多。