在对有关 systemd 的大量帖子、Youtube 视频和“文档”进行了大量搜索之后,我仍然不知所措。
链接 (https://wiki.archlinux.org/index.php/systemd#Create_custom_target)似乎很有希望,但(对我来说)有点模糊。
问题
如何创建一个自定义的 systemd 目标(IE: foo.target ),以便可以使用选择的 .service 单元启动?
例子
- 系统启动default.target(“foo.target”的符号链接)
- “foo.target”仅启动准系统 X 服务器和 GUI 程序,例如“gvim”。
原因
我只是想创建一个自定义目标来快速启动一个 X 程序。我很乐意排除所有我不需要的服务。
提前致谢!
答案1
通读man 5 systemd.unit
和man 5 systemd.target
告诉我们,单元文件用于定义目标以及 systemd 的其他所有内容。没有专门关于如何创建的文档目标,所以很难确定应该如何完成,但这与创建服务没有太大区别。
当您创建目标时,您需要符号链接target.wants
从 systemd services 目录到该目录。然后你可以设置/启动你的目标。根据您的示例,它可能如下所示。
/etc/systemd/system/foo.target
这是目标的单元文件。如果以graphical.target为例,我们可以使用它作为基础来创建我们自己的目标。
[Unit]
Description=Foobar boot target
Requires=multi-user.target
Wants=foobar.service
Conflicts=rescue.service rescue.target
After=multi-user.target rescue.service rescue.target
AllowIsolate=yes
解释 systemd 联机帮助页中的选项;
Description
——描述目标。你应该明白Requires
-- 目标的硬依赖性。您应该在启动自己的服务之前先启动基本系统Wants
——软依赖性。目标不要求这些就可以开始了。Conflicts
-- 如果一个单元与另一个单元有冲突设置,则启动前者将停止后者,反之亦然。After
-- 在这些服务之后启动AllowIsolate
-- 完全取决于您和您的环境。详细信息可在联机帮助页中找到systemd.unit(5)
/etc/systemd/system/foo.target.wants/
您将在该目录中链接为目标创建/需要的服务。相当于Wants=
单元文件中的选项。创建此目录,然后像这样创建符号链接;ln -s /usr/lib/systemd/system/bar.service /etc/systemd/system/foo.target.wants/bar.service
。这将创建一个从系统目录中的 bar.service 到 foo.target.wants 目录的符号链接。
我认为为服务创建单元文件有点超出了这个答案的范围,而且这个问题肯定有更多记录,所以我现在将其保留。创建单元文件时,只需将其符号链接到 target.wants 目录或将其添加到Wants=
指令中。
答案2
前面的答案中没有提到的是,为了让自定义 systemd 目标在启动时像 multi-user.target 一样工作,您必须以某种方式将其指定为启动过程的一部分。
基本上你想要做的是检查你当前的默认值是什么:systemctl get-default
。它很可能是graphical.target
或multi-user.target
。
然后,您需要在/etc/systemd/system
新的默认目标中创建符号链接,并确保您的目标是引导过程的扩展。
ln -s /etc/systemd/system/foo.target /etc/systemd/system/default.target
检查:
systemctl daemon-reload
systemctl get-default
如果multi-user.target
是您以前的默认值,您将需要在您的自定义单元中对其进行配置,如下所示,如 m32 所提到的:
[Unit]
Description=Foobar boot target
Requires=multi-user.target
Wants=foobar.service
Conflicts=rescue.service rescue.target
After=multi-user.target rescue.service rescue.target
AllowIsolate=yes
请注意,此处重要的一点是 multi-user.target 被指定为 Requires。有关所有含义的详细信息,请参阅 @m32 的答案。
您在这里所做的是使用您的自定义单元扩展启动过程。将其设置为 systemd 的默认值会指示 systemd 在启动时加载该单元。然后,该目标的配置会拉动任何其他目标,直到达到最基本的目标为止。至少我现在是这么理解的。
然后,就像其他答案中提到的那样,您可以在Wants=
指令中指定您的单元foo.target
并将其添加WantedBy=foo.target
到单元的安装部分。请注意,您仍然需要激活您想要在启动时使用的任何单元systemd enable foobar.service
。
总结一下:
- 创建您的目标作为现有目标的扩展
- 创建符号链接以使其成为您的默认目标
- 在您想要以此开始的所有单位中指定该目标
- 以这种方式启用您想要在启动时启动的任何单元
这篇关于运行级别的文档有更多细节:https://www.landoflinux.com/linux_runlevels_systemd.html
答案3
我强烈建议您在完成这项任务之前先看看这些例子,
vim /lib/systemd/system/*.target
请注意,如果您要创建自己的目标,则无需手动链接任何内容。
您只需将服务添加到/etc/systemd/system
并在其上运行即可systemctl enable
。只要它WantedBy
或RequiredBy
systemd 就会为您完成所有工作。