我读有两个单元文件文件夹(不在用户模式下)。
/usr/lib/systemd/system/: units provided by installed packages
/etc/systemd/system/: units installed by the system administrator
与这种理解相冲突的是这个问题的答案:如何编写Systemd的启动脚本。有人可以填写缺失的信息以便我了解发生了什么事吗? (更新:答案已更新,我的理解不再与之冲突。)
此外,脚本似乎组织在/etc/systemd/system/
文件夹内的子文件夹中:
getty.target.wants
multi-user.target.wants
在另一个地方我读到还有其他地方。这些似乎是针对特定用户的服务。
/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.
2015年8月31日更新:
为了其他人的利益,这里是我最近提出的相关问题的链接:我应该把 systemd 单元执行的脚本放在哪里?
答案1
最好放置的地方系统单位文件: /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
对应于文件系统上的预定义位置。这样,systemctl
就知道该单元依赖于一组名为的单元文件multi-user.target
(“目标”是用于指定单元依赖项组的术语。您可以使用 列出所有组systemctl list-units --type target
)。与目标一起加载的单元文件组被放置在一个targetname.target.wants
目录中。这只是一个充满符号链接(或真实的东西)的目录。如果您的[Install]
部分说它是,但如果目录中不存在指向它的符号链接,则它将不会加载WantedBy
。当 systemd 单元生成器在启动时将您的单元文件添加到依赖关系树缓存中(您可以使用 手动触发生成器)时,它会自动知道将符号链接放在哪里 - 在本例中,如果您启用它,则位于目录中。multi-user.target
multi-user.target.wants
systemctl daemon-reload
/etc/systemd/system/multi-user.target.wants/
手册要点:
其他单元可能会从不在单元加载路径上的目录加载到 systemd(“链接”)中。请参阅 systemctl(1) 的链接命令。
在systemctl下,查找单元文件命令
单元文件加载路径
请阅读并理解以下引用中的第一句话man systemd.unit
(因为这意味着如果您的 systemd 是使用不同的路径编译的,我在这里提到的所有路径可能不适用于您):
单元文件从编译期间确定的一组路径加载,如下两个表所述。在前面列出的目录中找到的单元文件将覆盖列表中较低目录中的同名文件。
设置变量后
$SYSTEMD_UNIT_PATH
,该变量的内容将覆盖单元加载路径。如果$SYSTEMD_UNIT_PATH
以空组件(“:”)结尾,则通常的单元加载路径将附加到变量的内容中。
表1和表2都man 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 04:00:00" systemctl --force reboot
这将产生一个瞬态单元文件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"
请注意,还有更危险的 double force 选项--force --force
,它告诉内核立即停止(并且,如果您不知道自己在做什么,则不安全,因为它几乎相当于切断电源)。
答案2
/etc/systemd/system
是你放置的地方你的脚本、pacman put包裹中的脚本/usr/lib/systemd/system
。
发出systemctl enable foo.service
会创建从/usr
到 的符号链接/etc
。man systemd.unit(5)
有关更多详细信息,请参阅 的单位负载路径部分。
答案3
如果您想了解 systemd 查找单元文件的所有位置,以下命令应该会有所帮助。
使用systemd-analyze
命令:
所有可以包含的文件夹用户服务:
这些是您可以放置自己的每用户配置的地方
systemd-analyze --user unit-paths
对于管理用户,您可能更喜欢将配置放在以下文件夹中(这些文件夹将影响所有用户):
systemd-analyze --global unit-paths
所有可以包含的文件夹系统服务:
这些很可能包含来自包管理器的已安装服务,并将影响整个系统
systemd-analyze --system unit-paths
看:联机帮助页
答案4
搜索路径
当你这样做时,有很多地方systemd
需要寻找systemctl enable <unit-name>
。无论它们在哪里被发现,它们都会被象征性地链接到内部的某个地方/etc/systemd
。
您可以查阅man systemd.unit(5)
完整列表,或使用systemd-analyze
其他答案中所述的命令。您可以将单元文件放在任何这些位置。但你必须注意precedence
和scope
。
Precedence
如果找到同名的单元文件,systemd 将优先选择哪些文件夹。
Scope
如用户、全局和系统。
选择文件夹
例如,如果您将单元文件放入~/.config/systemd/user.control
,那么您需要使用 来启用它们systemctl enable --user <unit-file>
。
通常,单元文件是针对服务的,而服务通常是针对主机的。因此,我主要只是将自定义单元放入/etc/systemd/system
系统范围内,并且优先于任何内容,以防出现名称冲突。
pkg-config systemd --variable=systemdsystemconfdir
pkg-config systemd --variable=systemduserunitdir
pkg-config systemd --variable=systemduserconfdir
在我的系统上,这些按顺序返回:
/etc/systemd/system
/usr/lib/systemd/user
/etc/systemd/user