黑入 SystemD

我构建嵌入式 Linux 系统已有十多年,并且广泛使用 sysV 风格的 init。它稳健且经过时间考验,但也有其局限性。现在有几个项目旨在取代 sysvinit,例如 Upstart 和 systemd。

我广泛使用 Fedora,既为无盘工作站构建 nfsroot 文件系统,也构建基于 Fedora 仓库的嵌入式固件。对于这类工作来说,Fedora 是个奇怪的选择;大多数人会选择 Debian 或 Ubuntu。

Fedora 在第 15 版时就迁移到了 systemd。由于 systemd 当时还很新,我决定不将我的工具链升级到 Fedora 15。现在我们用的是 17,而 systemd 看起来已经稳定了。因此我用 Fedora 17 构建了一个 nfsroot 系统。结果与 LTSP5/Meukow 类似,只不过所有软件包都新得多,因为 Fedora 提供的是较新的发行版本。

关于 systemd 的文档很稀少,我在研究如何精简 systemd 时遇到了一些麻烦。使用 sysvinit 时,精简更容易:你编辑 rc.sysinit 直到它足够精简,用 chkconfig 关闭无关服务,并禁用 SELinux。Fedora 团队发布了一些关于调整和使用 systemd 的有用文档。他们还有一份 sysVinit 到 systemd 速查表,以及一份调试指南。这些页面帮了我大忙。

我的 nfsroot 文件系统第一次尝试启动时失败了。通过将

systemd.confirm_spawn=true

添加到内核命令行,我能够确认 systemd 运行的每一条命令,并找出是哪一条崩溃了。

systemd 的一个有用特性是,它可以在 chroot 文件系统上运行 chkconfig 风格的命令,而无需 chroot 进去。这类似于 yum 的 --installroot 选项,我当初就是用它来构建文件系统的。例如,要在你刚构建好的系统上禁用 cron,请运行

systemctl --system --root=$TARGET disable crond.service

其中 $TARGET 是你 chroot 的路径。

Systemd 会启动一些无法用上述命令禁用的服务。这些服务/命令的符号链接也不存在于 /etc/systemd 中。我找到的唯一方法是从 /lib/systemd/system 中删除这些命令的符号链接。我发现其中一些在嵌入式/桌面系统中不必要的命令是:

/lib/systemd/system/sysinit.target.wants/*binfmt*
/lib/systemd/system/sysinit.target.wants/cryptsetup.target
/lib/systemd/system/sysinit.target.wants/dev-hugepages.target
/lib/systemd/system/basic.target.wants/fedora-configure.service
/lib/systemd/system/local-fs.target.wants/fedora-import-state.service
/lib/systemd/system/local-fs.target.wants/fedora-readonly.service
/lib/systemd/system/local-fs.target.wants/fedora-storage-init*.service