我最近创建了我的第一个自定义 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 脚本的正确位置是什么,为什么?
您完全正确地认为
/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
or的 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
.嗯……这是一个棘手的问题。假设这是不属于发行版的非操作系统代码,通常我会说它需要进入 /usr/local/lib/system 并从 /etc/systemd/system 链接到。这样做的问题是,如果在系统启动时没有安装所有文件系统,则可能会导致问题。因此,如果您感到幸运,您可以尝试将其命名为不太可能被升级覆盖的名称,并将其放置在包含其中大部分内容的同一目录中:/lib/systemd/system 并带有适当的链接。恕我直言。