我最近创建了第一个自定义 systemd 服务,以便在计算机启动序列的早期运行脚本。自定义.service
文件正在复制到/etc/systemd/system
,据我所知,这是自定义服务的正确位置,这些服务不是通过包或操作系统发行版的一部分进行部署的。
它是一种oneshot
类型服务,在启动网络堆栈和 dhcpcd 之前调用 shell 脚本来动态设置主机名。这是服务定义:
[Unit]
Description=Set hostname on startup, based on hardware serial number
Wants=local-fs.target
After=local-fs.target
Before=systemd-hostnamed.service network.target
[Service]
Type=oneshot
ExecStart=/SOMEPATH/hostname-from-serialnumber.sh
[Install]
WantedBy=systemd-hostnamed.service network.target
我不确定 shell 脚本的最佳位置是什么,所以我SOMEPATH
在上面的代码块中放置了一个占位符。该 shell 脚本的正确位置是什么?为什么?
答案1
您对于/etc/systemd/system/*.service
成为您的定制服务文件的合适位置是完全正确的。
至于你的脚本,把它放进去/usr/local/...
代替/usr/...
。那是因为这个剧本是你写的。以下是该约定存在的一些原因:
- 中的文件
/usr/{bin,lib,share}/
归包管理器所有。您应该能够dpkg -S <file>
、pacman -Qs <file>
或rpm -q --whatprovides <file>
在任何文件上找出哪个包拥有它。 - 您可以记住哪些文件是“您的”(即,如果您重建这台机器,很容易看到您需要复制的内容或您可以从包中获取的内容)
- 如果安装软件包,通用命名的脚本将不会被该软件包覆盖。
现在,您需要选择下一个目录。选项有:
/usr/local/bin
#!/bin/bash
: 如果您的脚本是可执行的(例如,编译的二进制文件或使用类似或 的shebang#!/usr/bin/python3
)并且可以由任何用户运行,则适用。我经常使用它,因为它非常简单。/usr/local/sbin
:如果您的脚本满足 的需要,则这是合适的/usr/local/bin
,但不应该由用户运行。相反,它应该仅由系统管理员运行。/usr/local/sbin
通常仅包含在$PATH
环境中sudo
。/usr/local/lib
:在某些系统(例如基于 Debian 的系统)上,此目录可能包含不打算由用户或 shell 脚本直接执行的内部二进制文件。然而,在其他系统(即基于 Redhat 的系统)上,lib
仅包括目标文件和库。/usr/local/libexec
:此目录包含不打算由用户或 shell 脚本直接执行的内部二进制文件。仅某些发行版支持此功能。/usr/local/share/<ServiceName>/
。这仅适用于您的脚本不可执行且与体系结构无关(即未编译)的情况。您有一个*.sh
脚本,但如果没有shebang
并且它不可执行,那么您需要通过调用解释器并将路径作为参数传递给该脚本来运行它。/bin/bash /path/to/script.sh
。在这种情况下,脚本可以被认为是一个只读的体系结构独立数据文件,应该以/usr/local/share
.最好将其放在另一个子目录中以避免混乱/usr/local/share
。您选择为您的服务编写的任何文档也可以纳入其中share
。
答案2
嗯……这是一个棘手的问题。假设这是非操作系统代码,不属于发行版,通常我会说它需要进入 /usr/local/lib/system 并从 /etc/systemd/system 链接到。这样做的问题是,如果系统启动时未安装所有文件系统,则可能会导致问题。因此,如果您感觉幸运,您可以尝试将其命名为不太可能被升级覆盖的名称,并将其放置在包含大多数内容的同一目录中:/lib/systemd/system 并带有适当的链接。恕我直言。