我在哪里放置我的 systemd 单元文件?

Jon*_*mar 132 directory-structure systemd

读到单元文件有两个文件夹(不在用户模式下)。

/usr/lib/systemd/system/: units provided by installed packages
/etc/systemd/system/: units installed by the system administrator
Run Code Online (Sandbox Code Playgroud)

与这种理解相冲突的是这个问题的答案:如何为 Systemd 编写启动脚本。有人可以填写缺失的信息以便我了解发生了什么吗?(更新:答案已更新,我的理解不再与之冲突。

此外,脚本似乎组织在文件夹内的子/etc/systemd/system/文件夹中:

getty.target.wants
multi-user.target.wants
Run Code Online (Sandbox Code Playgroud)

在另一个位置,我读到还有其他位置。这些似乎是针对用户特定的服务。

/usr/lib/systemd/user/ where services provided by installed packages go.
/etc/systemd/user/ where system-wide user services are placed by the system administrator.
~/.config/systemd/user/ where the user puts its own services.
Run Code Online (Sandbox Code Playgroud)

2015-08-31 更新:

为了其他人,这里是我最近问的一个相关问题的链接:我在哪里放置由 systemd 单元执行的脚本?

Jon*_*mar 129

放置系统单元文件的最佳位置: /etc/systemd/system 只需确保在 [Install] 部分下添加一个目标,阅读“它是如何知道的?” 详情。 更新/usr/local/lib/systemd/system是另一种选择,请阅读“灰色区域”了解详细信息。”

放置用户单元文件的最佳位置: /etc/systemd/user或者,$HOME/.config/systemd/user 但这取决于权限和情况。

事实是,systemd 单元(或如介绍句所称的“单元配置”)可以去任何地方——前提是您愿意制作手动符号链接并且您知道注意事项。systemctl daemon-reload出于一些充分的原因,将设备放在可以找到它的地方可以使生活更轻松:

  • 使用标准位置意味着 systemd 生成器会找到它们并在启动时使用systemctl enable. 这是因为您的单元将自动添加到单元依赖树(单元缓存)中。
  • 您不需要考虑权限,因为只有正确的特权用户才能写入指定区域。

它怎么知道?

以及如何确切systemctl enable知道在哪里创建符号链接?您可以在该[install]部分下的单元本身内对其进行硬编码。通常有一条线

[Install]
WantedBy = multi-user.target
Run Code Online (Sandbox Code Playgroud)

对应于文件系统上的预定义位置。这样,就systemctl知道该单元依赖于一组称为multi-user.target(“目标”是用于指定单元依赖组的术语。您可以使用 列出所有组systemctl list-units --type target)的单元文件组。与目标一起加载的单元文件组放在一个targetname.target.wants目录中。这只是一个充满符号链接(或真实的东西)的目录。如果你的[Install]部分说,这是WantedBymulti-user.target的,但如果一个符号链接它不存在的multi-user.target.wants目录,那么它不会加载。当 systemd 单元生成器在启动时将您的单元文件添加到依赖树缓存中时(您可以使用 手动触发生成器systemctl daemon-reload),它会自动知道将符号链接放在哪里——在这种情况下是在目录中/etc/systemd/system/multi-user.target.wants/ 你应该启用它。

手册中的要点:

其他单元可能会从不在单元加载路径上的目录加载到 systemd(“链接”)中。请参阅 systemctl(1) 的链接命令。

在 systemctl 下,查找Unit File Commands

单元文件加载路径

请阅读并理解以下引文中的第一句话man systemd.unit(因为这意味着如果您的 systemd 是使用不同路径编译的,我在此处提到的所有路径可能不适用于您):

单元文件从编译期间确定的一组路径加载,如下两个表所述。在前面列出的目录中找到的单元文件会覆盖列表中较低目录中具有相同名称的文件。

$SYSTEMD_UNIT_PATH设置变量后,此变量的内容将覆盖单元加载路径。如果$SYSTEMD_UNIT_PATH以空组件(“:”)结尾,则通常的单元加载路径将附加到变量的内容中。

表 1 和表 2man systemd.unit都很好。

在系统模式 ( --system)下运行时加载路径。

  • /etc/systemd/system 本地配置
  • /run/systemd/system 运行时单位
  • /usr/lib/systemd/system已安装包的单位(或/lib/systemd/system在某些情况下,阅读man systemd.unit

在用户模式下运行时的加载路径 ( --user)

每个用户单位和所有/全球用户单位之间存在差异。

用户依赖

  • $XDG_CONFIG_HOME/systemd/user 用户配置(仅在$XDG_CONFIG_HOME设置时使用)

  • $HOME/.config/systemd/user 用户配置(仅在$XDG_CONFIG_HOME未设置时使用)

  • $XDG_RUNTIME_DIR/systemd/user 运行时单位(仅在$XDG_RUNTIME_DIR设置时使用)

  • $XDG_DATA_HOME/systemd/user 已安装在主目录中的包的单​​位(仅在$XDG_DATA_HOME设置时使用)

  • $HOME/.local/share/systemd/user 已安装在主目录中的包的单​​位(仅在$XDG_DATA_HOME未设置时使用)

--global (全部用户)

适用于所有用户的单位——也就是每个用户都拥有的单位。因此,即使管理员在启动时启用了这些服务,每个用户也可以停止这些服务。

  • /etc/systemd/user 所有用户的本地配置 ( systemctl --global enable userunit.service)
  • /usr/lib/systemd/user 已为所有用户/lib/systemd/system在系统范围内安装的软件包单元(或在某些情况下,阅读 man systemd.unit)
  • /run/systemd/user 运行时单位

灰色地带

一方面,文件层次结构标准(也man file-hierarchy)指定/etc用于不执行二进制文件的本地配置。另一方面,它指定/usr/local/“供系统管理员在本地安装软件时使用”。您也可以争论(如果不仅仅是为了组织的目的)所有系统单元文件都应该放在 下/usr/local/lib/systemd/system,但这适用于属于“软件”的一部分而不是来自包管理器的单元文件。系统范围内的相应 systemd 用户单元可能位于 /usr/local/lib/systemd/user.

瞬态单元

另一个被遗忘的地方根本不存在!也许一个鲜为人知的程序是systemd-run. 您可以使用它来动态运行瞬态单元。见man systemd-run

例如,要安排明天早上 4 点重新启动(您可能需要 --force确保重新启动):

systemd-run -u restart --description="Restarts machine" --on-calendar="2020-12-18 00:04:00" systemctl --force reboot
Run Code Online (Sandbox Code Playgroud)

这将产生一个瞬态单元文件restart.service和一个相应的计时器(因为--on-calendar,由transient=yes.

/run/systemd/transient/restart.service

# This is a transient unit file, created programmatically via the systemd API. Do not edit.
[Unit]
Description=Restarts machine

[Service]
ExecStart=
ExecStart="/usr/bin/systemctl" "--force" "reboot"
Run Code Online (Sandbox Code Playgroud)

请注意,还有更危险的 double force option --force --force,它告诉内核立即停止(并且,如果您不知道自己在做什么,这是不安全的,因为它几乎等同于切断电源)。

  • @slm 是的,当问题提到 **我的** systemd 单元文件时,它旨在暗示自行创建的文件。 (2认同)

jas*_*yan 24

/etc/systemd/system是你把你的脚本,吃豆子放的脚本/usr/lib/systemd/system

发出systemctl enable foo.service会创建从/usr到的符号链接/etc。有关man systemd.unit(5)更多详细信息,请参阅单元负载路径​​部分。

  • 这个答案对于初学者来说更容易理解。 (2认同)

sma*_*c89 12

如果您想了解 systemd 查找单元文件的所有位置,以下命令应该会有所帮助。

使用systemd-analyze命令:

可以包含用户服务的所有文件夹:

这些是您可以放置​​自己的每用户配置的地方

systemd-analyze --user unit-paths
Run Code Online (Sandbox Code Playgroud)

对于管理用户,您可能更喜欢将配置放在以下文件夹中(这些文件夹将影响所有用户):

systemd-analyze --global unit-paths
Run Code Online (Sandbox Code Playgroud)

所有可以包含系统服务的文件夹:

这些很可能包含来自包管理器的已安装服务,并将影响整个系统

systemd-analyze --system unit-paths
Run Code Online (Sandbox Code Playgroud)

请参阅:联机帮助页


小智 5

Debian/Ubuntu 系统上的 /etc/systemd/system 和 /lib/systemd/system 之间的一个显着区别是,/lib/systemd/system 下的服务文件可以被屏蔽,而 /etc/systemd/system 下的服务文件则不能。例如,

# ls /lib/systemd/system/mytest.service
# systemctl mask mytest
# ls /etc/systemd/system/mytest2.service
# systemctl mask mytest2
Failed to mask unit: File /etc/systemd/system/mytest2.service already exists.
Run Code Online (Sandbox Code Playgroud)