在Debian中用OpenRC替换Systemd

Hacker News Top 工具

摘要

在Debian上使用OpenRC替换Systemd的指南,包括安装步骤和面临的挑战。

暂无内容
查看原文
查看缓存全文

缓存时间: 2026/06/29 08:02

# Daniel Cordova 来源:https://danielcordova.me/blog/debian-openrc/ ## 太长不看 我并不是**systemd**的反对者,但也不完全赞成它的使用方式。说白了,如果它适合你,那就没问题。 然而*我的情况*更像是**好奇心与不适感**的交织。*好奇*在于 init 系统是如何工作的,而*不适*则源于*systemd*如何整合各种功能或新特性。我知道它在大多数使用场景下都运行良好(我从它早期就开始用了),也同意*systemd*违背了**KISS**哲学的几乎所有原则,但其他项目不也这样吗? **那么为什么会有不适感?** 这要从一段时间前说起。当时我看到新闻,讨论这个项目如何逐渐接管本应属于其他项目的职责,以及一些**生产环境部署**因为某个破坏性变更而严重失败——如果那个职责不属于*systemd*,本可避免。不过对我来说这还不算太糟。真正让我第一次感到不安的,是**年龄验证法律**(https://github.com/BryanLunduke/DoesItAgeVerify)正在酝酿,我当时天真地想:“好吧,Windows 和 Mac 会集成它,但 Linux 和其他开源 OS 及项目肯定会‘反抗’这种荒谬的法律!!” 然后我转念一想:“等等,什么?这条法律在一些州/国家甚至还没通过,systemd 就已经集成了?为什么?以往那种对无意义法律的‘反抗’精神去哪儿了?” > 我当时挺生气的,我知道,我不是那个项目的贡献者,而且*它只是一个可选字段*,但**感觉完全不对**。那位开发者遭受的群嘲也同样不对。 随后第二次不适感来自我阅读科技新闻时,发现这条:systemd 集成了 sys-install(https://www.muylinux.com/2026/06/22/systemd-261/)`systemd 集成了自己的“系统安装器”,名为 'systemd-sysinstall',以及其他功能`。 好吧,一个 init 系统承担大量职责是一回事,但从 PID 1 变成系统安装器是另一回事。不管你怎么包装这个想法,**“Init 系统的职责”** 和 **“systemd 的奇怪职责与愿望”** 之间有着天壤之别。于是**好奇心**作祟,我决定尝试在我的 *Thinkpad X13s Snapdragon*(https://danielcordova.me/blog/linux-x13s-snapdragon/)上安装 **OpenRC**(https://wiki.gentoo.org/wiki/OpenRC),这台笔记本我用来在家搞搞黑客、测试点东西等等。顺便说一句,这台笔记本运行的是 **Debian**。 ## 安装 在 **Debian Testing** 中安装 **OpenRC** 并不难,但也算不上简单操作。我在关于 apt-get 和 apt 如何处理**essential 包**时遇到了一些挑战和问题。 ### 挑战 在尝试安装 *OpenRC* 并同时卸载 *Systemd* 时,我遇到了两个主要挑战: - *apt-get* 根本无法卸载 *systemd*,只会报错说不可行 - *apt* 显示的错误信息更好一些,解释了为什么不能卸载 systemd 稍微挖掘并阅读了一些网页后,我了解到需要给 **apt** 传递一个参数,才能卸载一个 **essential** 包。所以卸载命令大概是这样: `` sudo apt purge --allow-remove-essential systemd `` > **先别复制粘贴。** 在删除 *systemd* 之前,需要确保 *OpenRC* 将被安装,因此命令应该是: `` sudo apt purge --allow-remove-essential systemd && sudo apt install openrc sysvinit-core `` > 该命令会卸载 systemd 并安装一些以后可能不需要的依赖。 ### 问题 安装 *OpenRC* 并卸载 *systemd* 后,系统无法正常启动,所以我不得不进入**恢复模式**并按 **Ctrl-D** 才能修复错误。 问题本身是:卸载 *systemd* 时,不知何故 *OpenRC* 也被移除了,或者根本没安装成功。于是我进入*恢复模式*,连接到 WiFi 网络,然后用 `apt install openrc sysvinit-core` 重新安装了 *OpenRC*。 到目前为止一切顺利。但**电池状态和音频**都不工作。我知道*电池状态*问题是因为在笔记本上安装 **Debian Testing** 时遇到的**内核回归**(https://lwn.net/ml/linux-kernel/[email protected]/)。于是我将 *systemd* 服务转换成一个脚本,并放入 `/etc/init.d/`,这样 *OpenRC* 就可以启动或启用它。成功了。至于音频,我觉得需要另一个与 pipewire 和 wireplumber 相关的服务,或者在登录时启动它们。我以后再测试。 Systemd 服务: `` [Unit] Description=Start Qualcomm remoteprocs (SLPI/ADSP/CDSP) DefaultDependencies=no After=initrd-root-fs.target local-fs.target Before=sysinit.target [Service] Type=oneshot RemainAfterExit=yes ExecStart=/bin/sh -c 'echo start > /sys/class/remoteproc/remoteproc0/state; echo start > /sys/class/remoteproc/remoteproc1/state; echo start > /sys/class/remoteproc/remoteproc2/state' [Install] WantedBy=sysinit.target `` OpenRC 脚本 `` #!/bin/sh echo start > /sys/class/remoteproc/remoteproc0/state; echo start > /sys/class/remoteproc/remoteproc1/state; echo start > /sys/class/remoteproc/remoteproc2/state; `` > 我需要把它转换成规范的 **OpenRC** 脚本 ## 未来 目前 **OpenRC** 能胜任工作。我不确定它是否会成为我未来长期的默认 **Init 系统**,但我觉得这次实验是成功的。 我将在接下来的几天(也许几周)继续在我的 *"家庭黑客笔记本"* 上测试 **OpenRC**,如果感觉足够舒适,我也会将我的工作笔记本(同样运行 Debian Testing,并使用了相同的 dotfiles)迁移到 **OpenRC**。 尽管在现有的 **Linux** 安装上更换 *Init 系统* 存在一些麻烦和挑战,可能不是最佳选择,但我对目前的结果感到满意。 如果这对你也适用,那么我会更高兴知道你也在抛弃 *systemd* 而选择 *OpenRC*。*不开玩笑*,这归根结底是 Unix 自由的一部分——**使用任何你想要的东西,任何适合你的东西。** Happy Hacking!! ## 链接 如果你也对 **OpenRC** 感兴趣,这里有一些链接: - Debian: Switching Init System Easily (OpenRC, Sysvinit, Runit) (https://lecorbeausvault.wordpress.com/2022/02/07/debian-switching-init-system-easily-openrc-sysvinit-runit/) - Beyond systemd: A Technical Deep Dive into OpenRC for Modern Linux Systems (https://linux-digest.com/beyond-systemd-a-technical-deep-dive-into-openrc-for-modern-linux-systems) - Introduction to OpenRC: Managing Services with Ease (https://www.foxipex.com/2024/11/15/introduction-to-openrc-managing-services-with-ease/) - OpenRC on debian (https://members.loria.fr/EJeandel/posts/openrc/)

相似文章

我的新家庭服务器软件选择

Lobsters Hottest

一篇个人博客文章,详细描述了作者为新家庭服务器选择操作系统和服务管理软件的经历,比较了Synology、TrueNAS、Debian以及使用Runit的Void Linux。

# 制作 Debian 或 Fedora 持久化 Live 镜像

Hacker News Top

# 为 Debian、Fedora 和 Ubuntu 创建持久化 Live USB 镜像 Live USB 是快速启动 Linux 环境的绝佳方式,但默认情况下,每次重启后所有更改都会丢失。**持久化存储**功能可以将你的文件、配置和已安装的软件包保留下来。遗憾的是,各发行版对这一功能的实现方式并不统一——每个发行版都有自己的一套做法,内核参数、分区标签和文件系统结构各不相同。 本文将介绍如何通过注入 ext4 分区并利用 OverlayFS 的持久化机制,为 Debian、Fedora 和 Ubuntu 创建持久化 Live USB。此外还会介绍一个不需要重新构建镜像、直接修改 ISO 启动参数的"野路子"字节替换技巧。 --- ## 背景:Live 系统如何实现持久化 大多数现代 Linux Live 系统使用 **OverlayFS** 将只读的压缩根文件系统(通常是 SquashFS)与可写的上层目录叠加在一起。启动时,内核或 initramfs 会在只读层之上挂载一个可写层,使系统看起来像一个完整的可读写文件系统。 持久化功能的原理是:将这个上层目录(overlay upperdir)存放到 USB 驱动器上一个**可写的持久化分区**中,而不是放在内存中。 **挑战在于**:每个发行版寻找持久化分区的方式都不一样: - **Ubuntu/Debian**:使用内核参数 `persistent`,并查找标签为 `casper-rw` 或 `persistence` 的分区 - **Fedora**:使用内核参数 `rd.live.overlay`,并查找标签为 `overlay` 的分区 - **各发行版**的 initramfs 脚本、overlay 目录结构和文件系统要求也各有差异 --- ## 工具准备 ```bash # 安装所需工具 sudo apt install gdisk e2fsprogs util-linux # Debian/Ubuntu sudo dnf install gdisk e2fsprogs util-linux # Fedora ``` 你还需要: - 一个容量足够的 USB 驱动器(建议 16GB 以上) - 目标发行版的 ISO 镜像 - `root` 权限 - (可选)用于字节替换技巧的十六进制编辑器 --- ## 第一步:将 ISO 写入 USB 首先,按照常规方式将 ISO 写入 USB 驱动器: ```bash # 找到你的 USB 设备 lsblk # 写入 ISO(请将 /dev/sdX 替换为实际的设备名) sudo dd if=ubuntu-24.04-desktop-amd64.iso of=/dev/sdX bs=4M status=progress oflag=sync ``` **注意**:`dd` 写入后,分区表反映的是 ISO 内部的布局。ISO 镜像通常不会占满整个 USB 驱动器,末尾会留有大量未使用的空间——我们将利用这部分空间创建持久化分区。 --- ## 第二步:添加持久化分区 ISO 写入后,USB 末尾应有未分配的空间。我们将在这里创建一个新的 ext4 分区。 ### 查看当前分区布局 ```bash sudo gdisk -l /dev/sdX ``` 记下最后一个分区的结束扇区,新分区将从下一个扇区开始。 ### 创建新分区 ```bash sudo gdisk /dev/sdX ``` 在 `gdisk` 交互界面中: ``` Command: n # 新建分区 Partition number: (接受默认值) First sector: (接受默认值,即紧接上一分区之后) Last sector: (接受默认值,使用全部剩余空间;或指定大小,如 +8G) Hex code: 8300 # Linux 文件系统 Command: w # 写入并退出 ``` ### 格式化分区 这是关键步骤——**分区标签必须与发行版的 initramfs 脚本所期望的完全一致**。 #### Ubuntu(casper) ```bash sudo mkfs.ext4 -L casper-rw /dev/sdX3 ``` Ubuntu 的 `casper` initramfs 脚本会扫描所有已挂载的设备,查找标签为 `casper-rw` 的分区。 #### Ubuntu(较新版本使用 persistence) 某些 Ubuntu 版本和 Ubuntu 衍生版使用不同的标签: ```bash sudo mkfs.ext4 -L persistence /dev/sdX3 ``` 使用 `persistence` 标签时,还需要在分区根目录创建一个配置文件: ```bash sudo mount /dev/sdX3 /mnt echo "/ union" | sudo tee /mnt/persistence.conf sudo umount /mnt ``` #### Debian(live-boot) ```bash sudo mkfs.ext4 -L persistence /dev/sdX3 # 挂载并创建配置文件 sudo mount /dev/sdX3 /mnt echo "/ union" | sudo tee /mnt/persistence.conf sudo umount /mnt ``` Debian 的 `live-boot` 包需要 `persistence.conf` 文件来指定哪些目录应该被持久化。`/ union` 表示使用 union 挂载方式持久化整个根目录。 #### Fedora(dracut) ```bash sudo mkfs.ext4 -L overlay /dev/sdX3 ``` Fedora 使用 `dracut` 而非 `casper`,其持久化机制完全不同。`dracut` 的 `dmsquash-live` 模块会查找标签为 `overlay` 的分区。 --- ## 第三步:修改内核启动参数 创建好分区后,还需要在启动参数中告诉内核(或 initramfs)启用持久化功能。有三种方式可以实现。 ### 方式一:在启动菜单中手动编辑(适合测试) 启动时,在 GRUB 或 syslinux 菜单处按 `e`(GRUB)或 `Tab`(syslinux),然后手动添加参数: **Ubuntu/Debian:** ``` persistent ``` **Fedora:** ``` rd.live.overlay=LABEL=overlay rd.live.overlay.overlayfs=1 ``` ### 方式二:修改 USB 上的配置文件(推荐) 如果 USB 上的 EFI 或 syslinux 分区可写,可以直接修改配置文件。 挂载 EFI 分区: ```bash sudo mount /dev/sdX2 /mnt ``` 找到启动配置文件: ```bash find /mnt -name "grub.cfg" -o -name "isolinux.cfg" -o -name "*.conf" | head -20 ``` **对于 Ubuntu 的 grub.cfg:** ```bash sudo nano /mnt/boot/grub/grub.cfg ``` 找到 `linux` 行,添加 `persistent`: ``` linux /casper/vmlinuz boot=casper persistent quiet splash --- ``` **对于 Fedora 的 grub.cfg:** ``` linux /images/pxeboot/vmlinuz rd.live.image rd.live.overlay=LABEL=overlay rd.live.overlay.overlayfs=1 quiet ``` ### 方式三:字节替换技巧(无需重新构建 ISO) 这是最"野路子"的方法,但在 USB 上的文件系统为只读时(如某些混合 ISO 镜像)非常有用。其原理是:直接在 ISO/USB 设备的原始字节层面,将现有的内核参数替换为新的参数。 **前提条件**:替换后的字符串长度必须与原字符串**完全相同**,不足的部分用空格或空字节填充。 #### 查找参数字符串 ```bash # 在设备中搜索目标字符串 sudo grep -c "boot=casper" /dev/sdX # 确认字符串存在 sudo grep -oba "boot=casper" /dev/sdX | head -5 ``` `grep -oba` 会输出字符串的字节偏移量: ``` 12345678:boot=casper ``` #### 使用 Python 执行字节替换 ```python #!/usr/bin/env python3 """ ISO/USB 内核参数字节替换工具 警告:直接修改块设备——操作前务必备份! """ import sys device = "/dev/sdX" # 原始字符串(长度必须与替换字符串一致) old_param = b"boot=casper" # 新字符串(添加 persistent 参数) new_param = b"boot=casper persistent" # 注意:两者长度不同,需要调整 # 更实用的示例:在现有参数中添加 'persistent' # 找一个可以安全覆盖的较长字符串 old_string = b"boot=casper quiet splash" new_string = b"boot=casper persistent " # 用空格填充,保持长度相同 assert len(old_string) == len(new_string), "字符串长度必须相同!" print(f"原始字符串:{old_string}") print(f"替换字符串:{new_string}") print(f"长度:{len(old_string)} 字节") with open(device, "r+b") as f: data = f.read() count = data.count(old_string) print(f"找到 {count} 处匹配") if count == 0: print("未找到目标字符串,请检查参数") sys.exit(1) # 替换所有匹配项 new_data = data.replace(old_string, new_string) f.seek(0) f.write(new_data) print("替换完成!") ``` > ⚠️ **警告**:直接写入块设备极具风险。操作前务必确认设备名称,并做好备份。 #### 更安全的替换方式(按偏移量操作) ```python #!/usr/bin/env python3 """按偏移量进行精确字节替换""" import subprocess import sys device = sys.argv[1] if len(sys.argv) > 1 else "/dev/sdX" old_bytes = b"boot=casper quiet" new_bytes = b"boot=casper persi" # 长度相同 # 使用 grep 查找偏移量 result = subprocess.run( ["grep", "-oba", old_bytes.decode(), device], capture_output=True, text=True ) offsets = [] for line in result.stdout.strip().split('\n'): if ':' in line: offset = int(line.split(':')[0]) offsets.append(offset) print(f"在以下偏移量找到匹配:{offsets}") with open(device, "r+b") as f: for offset in offsets: f.seek(offset) found = f.read(len(old_bytes)) print(f"偏移量 {offset} 处:{found}") # 确认后再写入 confirm = input("是否替换?(y/N) ") if confirm.lower() == 'y': f.seek(offset) f.write(new_bytes) print(f"已替换偏移量 {offset} 处的内容") print("操作完成") ``` --- ## 各发行版详细说明 ### Ubuntu(casper) Ubuntu 使用 `casper` 包处理 Live 系统启动。持久化功能的相关代码位于 `/usr/share/initramfs-tools/scripts/casper` 及其模块目录中。 **工作原理:** 1. casper 在启动时扫描所有块设备 2. 查找标签为 `casper-rw` 的分区,或包含 `persistence.conf` 的 `persistence` 分区 3. 使用 OverlayFS 将其挂载为上层目录 4. 将合并后的文件系统作为根目录挂载 **完整配置示例:** ```bash # 1. 写入 ISO sudo dd if=ubuntu-24.04-desktop-amd64.iso of=/dev/sdX bs=4M status=progress # 2. 创建持久化分区 sudo gdisk /dev/sdX # n -> 默认 -> 默认 -> 默认 -> 8300 -> w # 3. 格式化(使用 casper-rw 标签) sudo mkfs.ext4 -L casper-rw /dev/sdX3 # 4. 修改启动参数(如果 EFI 分区可写) sudo mount /dev/sdX2 /mnt/efi sudo sed -i 's/boot=casper/boot=casper persistent/g' /mnt/efi/boot/grub/grub.cfg sudo umount /mnt/efi ``` ### Debian(live-boot) Debian 的 Live 系统使用 `live-boot` 包,其配置方式与 Ubuntu 的 casper 类似,但有一些重要区别。 **工作原理:** 1. live-boot 查找标签为 `persistence` 的分区 2. 读取分区根目录的 `persistence.conf` 文件 3. 根据配置文件的指令创建 OverlayFS **`persistence.conf` 格式:** ``` # 持久化整个根目录(最常用) / union # 或者只持久化特定目录 /home union /etc union ``` **完整配置示例:** ```bash # 1. 写入 ISO sudo dd if=debian-12.0.0-amd64-live-gnome.iso of=/dev/sdX bs=4M status=progress # 2. 创建并格式化持久化分区 sudo gdisk /dev/sdX # 新建分区 sudo mkfs.ext4 -L persistence /dev/sdX3 # 3. 创建 persistence.conf sudo mount /dev/sdX3 /mnt echo "/ union" | sudo tee /mnt/persistence.conf sudo umount /mnt # 4. 修改启动参数(添加 persistence 参数) # 在 GRUB 菜单中手动添加,或修改配置文件 ``` **Debian 需要的内核参数:** ``` persistence persistence-label=persistence ``` 或仅使用: ``` persistence ``` (`live-boot` 会自动查找 `persistence` 标签的分区) ### Fedora(dracut + dmsquash-live) Fedora 的 Live 系统机制与 Debian/Ubuntu 完全不同,使用 `dracut` 和 `dmsquash-live` 模块。 **工作原理:** 1. dracut 的 `dmsquash-live` 模块处理 SquashFS 根文件系统的挂载 2. 通过 `rd.live.overlay` 参数指定 overlay 分区 3. 使用 device mapper 而非直接使用 OverlayFS(取决于版本) **Fedora 持久化分区设置:** ```bash # 1. 写入 ISO sudo dd if=Fedora-Workstation-Live-x86_64-39.iso of=/dev/sdX bs=4M status=progress # 2. 创建持久化分区 sudo gdisk /dev/sdX # 新建分区 sudo mkfs.ext4 -L overlay /dev/sdX4 # 注意:Fedora 有更多默认分区 # 3. 修改 GRUB 参数(添加以下内容) # rd.live.overlay=LABEL=overlay rd.live.overlay.overlayfs=1 ``` **Fedora 所需的内核参数:** ``` rd.live.image rd.live.overlay=LABEL=overlay rd.live.overlay.overlayfs=1 ``` 如需重置 overlay(丢弃所有持久化更改),可添加: ``` rd.live.overlay.reset ``` --- ## 故障排查 ### 持久化功能不生效 **检查分区标签:** ```bash sudo blkid /dev/sdX3 # 应显示:LABEL="casper-rw" 或 LABEL="persistence" 或 LABEL="overlay" ``` **检查内核参数:** ```bash cat /proc/cmdline # 应包含 persistent(Ubuntu/Debian)或 rd.live.overlay(Fedora) ``` **检查 Live 系统日志:** ```bash # Ubuntu/Debian dmesg | grep -i "casper\|persist\|overlay" journalctl -b | grep -i "live\|persist" # Fedora dmesg | grep -i "overlay\|live" ``` ### USB 重启后无法识别 部分 BIOS/UEFI 对 GPT 磁盘(而非混合 MBR)的兼容性存在问题。可尝试以下方法: ```bash # 混合 MBR 写入(如有必要) sudo gdisk /dev/sdX # 进入 expert 菜单:x # 创建混合 MBR:h # 按提示操作,选择前 3 个分区 ``` ### Fedora overlay 分区未找到 Fedora 的 dracut 有时在识别 overlay 分区时存在时序问题。可尝试添加以下参数: ``` rd.live.overlay=LABEL=overlay rootflags=noatime ``` 或直接使用设备路径代替标签: ``` rd.live.overlay=/dev/sdb4 ``` ### 分区空间已满 ```bash # 查看持久化分区使用情况(在 Live 系统中执行) df -h /run/live/persistence/sdb3 # Debian/Ubuntu df -h /run/overlayfs # Fedora # 清理 apt 缓存 sudo apt clean sudo apt autoremove ``` --- ## 局限性与注意事项 ### 内核更新 内核更新是持久化 Live 系统的一大痛点。由于内核文件存储在只读的 ISO 部分,常规的 `apt upgrade` 或 `dnf upgrade` 无法更新内核。可以安装内核,但新内核的 GRUB 条目不会生效,因为 GRUB 配置同样位于只读区域。 **解决方法**:手动将新内核文件复制到可写的 EFI 分区,并更新 GRUB 配置——但这需要额外的手动操作,本文不作详述。 ### 性能 持久化 overlay 层会带来一定的性能开销,因为每次文件系统操作都需要经过 OverlayFS 层。对于写入密集型任务,建议使用高速 USB 3.0 驱动器。 ### 跨发行版兼容性差 如前所述,各发行版之间缺乏标准化: | 发行版 | initramfs | 参数 | 分区标签 | 配置文件 | |--------|-----------|------|----------|----------| | Ubuntu(旧版)| casper | `persistent` | `casper-rw` | 不需要 | | Ubuntu(新版)| casper | `persistent` | `persistence` | 需要 | | Debian | live-boot | `persistence` | `persistence` | 需要 | | Fedora | dracut | `rd.live.overlay` | `overlay` | 不需要 | 这意味着:同一个 USB 驱动器无法同时为多个发行版提供持久化支持(至少不能轻松实现)。 ### 字节替换技巧的局限性 字节替换方法虽然便捷,但存在一些限制: - 新旧字符串长度必须相同 - 如果参数被压缩或哈希校验,替换会失败 - 某些 GRUB 版本会对配置文件进行校验,替换后可能无法启动 - UEFI Secure Boot 环境下可能遇到额外的校验问题 --- ## 总结 为不同的 Linux 发行版创建持久化 Live USB 是完全可行的,但因为缺乏统一标准,每个发行版都需要单独对待: 1. **Ubuntu** 使用 casper,需要 `casper-rw` 或 `persistence` 标签,以及 `persistent` 内核参数 2. **Debian** 使用 live-boot,需要 `persistence` 标签、`persistence.conf` 文件,以及 `persistence` 内核参数 3. **Fedora** 使用 dracut,需要 `overlay` 标签,以及 `rd.live.overlay` 内核参数 字节替换技巧为修改只读 ISO 的启动参数提供了一种无需重新构建镜像的快捷方式,但使用时需格外谨慎。 希望 Linux 社区未来能够在 Live 系统持久化功能上实现更好的标准化——但就目前而言,了解这些底层细节对于让持久化 Live USB 正常工作仍然是必要的。