编写Systemd service 配置文件

编写Systemd service 配置文件

# man systemd.service

中文参考手册 systemd.unit https://kinvolk.io/docs/flatcar-container-linux/latest/setup/systemd/environment-variables/

Systemd 单元文件中的以 “#” 开头的行后面的内容会被认为是注释

Systemd 下的布尔值,1、yes、on、true 都是开启,0、no、off、false 都是关闭。

Systemd 下的时间单位默认是秒,所以要用毫秒(ms)分钟(m)等请显式说明。

配置文件存放位置

/usr/lib/systemd/system/ 
/etc/systemd/system

Systemd 单元类型有:

类型 描述
Target A group of units that defines a synchronization point. The synchronization point is used at boot time to start the system in a particular state.
Service A unit of this type starts, stops, restarts or reloads a service daemon such as Apache webserver.
Socket A unit of this type activates a service when the service receives incoming traffic on a listening socket.
Device A unit of this type implements device-based activation such as a device driver.
Mount A unit of this type controls the file-system mount point.
Automount A unit of this type provides and controls on-demand mounting of file systems.
Swap A unit of this type encapsulates/activates/deactivates swap partition.
Path A unit of this type monitors files/directories and activates/deactivates a service if the specified file or directory is accessed.
Timer A unit of this type activates/deactivates specified service based on a timer or when the set time is elapsed.
Snapshot A unit that creates and saves the current state of all running units. This state can be used to restore the system later.
Slice A group of units that manages system resources such as CPU, and memory.
Scope A unit that organizes and manages foreign processes.
busname A unit that controls DBus system.

可以使用systemctl -t help 命令列出所有支持的单元。

依赖关系

  • Requires 这个单元启动了,那么Requires单元也会被启动; Requires单元被停止了,这个单元也会停止,是强依赖关系。Requires并不能控制启动顺序,通常是本单元和Requires单元并行启动的。这个选项不能作为启动顺序保证。
  • RequiresOverridableRequires 类似。只不过是如果这个服务是用户手动启动的,那么 RequiresOverridable 即使启动不成功也不报错。如果不是手动启动的,和Requires一样。
  • Requisite 强势版本的 Requires,Requisite必须已经处于全部成功,否则本单元会马上进入启动失败的状态。且系统不会尝试去启动未成功启动的Requisite单元。
  • Wants:本单元启动后,want单元也会被启动。但是本单元与wants是弱依赖关系。
  • Conflicts 当此单元启动的时候,Conflicts的所有单元都将被停止。
  • OnFailure 当该单元进入失败状态时,将会启动OnFailure中的单元

启动顺序

Before/After 用于强制指定单元之间的先后顺序。且停止顺序与启动顺序正好相反。这两个选项仅用于指定先后顺序,而与 Requires, Wants, BindsTo 这些选项没有任何关系。

启动类型

  • simple 如果设为 simple (当设置了 ExecStart= 、但是没有设置 Type=BusName= 时,这是默认值),那么 ExecStart= 进程就是该服务的主进程,并且 systemd 会认为在创建了该服务的主服务进程之后,该服务就已经启动完成。如果此进程需要为系统中的其他进程提供服务,那么必须在该服务启动之前先建立好通信渠道(例如套接字),这样,在创建主服务进程之后、执行主服务进程之前,即可启动后继单元,从而加快了后继单元的启动速度。这就意味着对于 simple 类型的服务来说, 即使不能成功调用主服务进程(例如 User= 不存在、或者二进制可执行文件不存在),systemctl start也仍然会执行成功。

  • forking 标准 Unix Daemon 使用的启动方式。启动程序后会调用 fork() 函数,把必要的通信频道都设置好之后父进程退出,留下守护精灵的子进程。你要是使用的这种方式,最好也指定下 PIDFILE=,以帮助 systemd 准确可靠的定位该服务的主进程。systemd 将会在父进程退出之后立即开始启动后继单元。

  • oneshot oneshotsimple 类似,不同之处在于,只有在该服务的主服务进程退出之后,systemd 才会认为该服务启动完成,才会开始启动后继单元。此种类型的服务通常需要设置 RemainAfterExit= 选项。当 Type=ExecStart= 都没有设置时, Type=``oneshot 就是默认值。
  • dbus 这个程序启动时需要获取一块 DBus 空间,所以需要和 BusName= 一起用。只有它成功获得了 DBus 空间,依赖它的程序才会被启动。
  • notify notifyexec 类似,不同之处在于,该服务将会在启动完成之后通过sd_notify(3)之类的接口发送一个通知消息。systemd 将会在启动后继单元之前,首先确保该进程已经成功的发送了这个消息。如果设为此类型,那么下文的 NotifyAccess=将只能设为非 none 值。如果未设置NotifyAccess= 选项、或者已经被明确设为 none ,那么将会被自动强制修改为main 。注意,目前 Type=notify 尚不能与PrivateNetwork=yes 一起使用。
  • idle idlesimple 类似,不同之处在于,服务进程将会被延迟到所有活动任务都完成之后再执行。这样可以避免控制台上的状态信息与shell脚本的输出混杂在一起。注意:(1)仅可用于改善控制台输出,切勿将其用于不同单元之间的排序工具;(2)延迟最多不超过5秒,超时后将无条件的启动服务进程。

定义流程

定义控制单元 [Unit]

[Unit]
Description= 描述这个单元

定义服务体 [Service]

[Service]
Type= 启动类型

安装服务 [Install]

[Install]
WantedBy=multi-user.target 

Alias=给你自己的别名,这样 systemctl command xxx.service 的时候就可以不输入完整的单元名称。比如你给 NetworkManager 一个别名叫 Alias=nm,那你就可以 systemctl status nm.service 查看实际是 NetworkManager.service 的服务了。

Also=安装本服务的时候还要安装别的什么服务。比如我们的 He.net 脚本按理应该需要一个 iproute2.service 作为 also,但是 iproute2 实际上不需要 systemd 控制,所以就没写。它和 [Unit] 定义里面的依赖关系相比,它管理的不是运行时依赖,而是安装时。安装好了之后启动谁先谁后,谁依赖谁,和 Also= 都没有关系。

示例

Network Manager

[Unit]
Description=Network Manager
Documentation=man:NetworkManager(8)
Wants=network.target
After=network-pre.target dbus.service
Before=network.target 

[Service]
Type=dbus
BusName=org.freedesktop.NetworkManager
ExecReload=/usr/bin/busctl call org.freedesktop.NetworkManager /org/freedesktop/NetworkManager org.freedesktop.NetworkManager Reload u 0
#ExecReload=/bin/kill -HUP $MAINPID
ExecStart=/usr/sbin/NetworkManager --no-daemon
Restart=on-failure
# NM doesn't want systemd to kill its children for it
KillMode=process
CapabilityBoundingSet=CAP_NET_ADMIN CAP_DAC_OVERRIDE CAP_NET_RAW CAP_NET_BIND_SERVICE CAP_SETGID CAP_SETUID CAP_SYS_MODULE CAP_AUDIT_WRITE CAP_KILL CAP_SYS_CHROOT

ProtectSystem=true
ProtectHome=read-only

[Install]
WantedBy=multi-user.target
Also=NetworkManager-dispatcher.service

# We want to enable NetworkManager-wait-online.service whenever this service
# is enabled. NetworkManager-wait-online.service has
# WantedBy=network-online.target, so enabling it only has an effect if
# network-online.target itself is enabled or pulled in by some other unit.
Also=NetworkManager-wait-online.service
qrcode

创建时间:2021-10-23 16:31:00

最后修改:2021-11-03 03:25:28