Home systemd 服务编写基础
Post
Cancel

systemd 服务编写基础

Convert A SysV Init Script Into A systemd Service File

传统的Unix/Linux服务(守护进程)是通过SysV初始化脚本启动的。这些是Bourne Shell脚本,通常放在 /etc/rc.d/init.d/ 这样的目录中。 配合使用一些标准参数,如start, stop或restart等控制,实现启动,停止或重新启动有关的服务。

Systemd提供了与这些shell脚本的兼容性,建议为安装的所有守护进程安装本机Systemd服务文件。

对于守护进程,systemd附带的daemon(7)手册页包含了许多关于这方面的有用信息。

1
2
3
4
5
6
$ man 7 daemon

A daemon is a service process that runs in the background and supervises the system or provides functionality to other processes.
Traditionally, daemons are implemented following a scheme originating in SysV Unix. Modern daemons should follow a simpler yet more
powerful scheme (here called "new-style" daemons), as implemented by systemd(1). This manual page covers both schemes, and in
particular includes recommendations for daemons that shall be included in the systemd init system.

编写一个简单的service文件。示例的abrtd程序是Fedora上的一个Automatic Bug Reporting Tool, 其需要在syslog启动后运行。

1
2
3
4
5
6
7
8
9
10
[Unit]
Description=Daemon to detect crashing apps
After=syslog.target

[Service]
ExecStart=/usr/sbin/abrtd
Type=forking

[Install]
WantedBy=multi-user.target

简单解释: [Unit]部分包含关于服务的基本信息。Systemd不仅可以管理系统服务,还可以管理设备、挂载点、定时器等系统组件。 systemd中所有这些对象的通用术语是一个单元,[Unit]一节编码了关于它的信息,这些信息不仅适用于服务,还适用于systemd维护的其他单元类型。 以上示例中,配置了守护进程将在Syslog(2)之后启动。syslog.target是systemd中的一个特殊目标单元,是引入syslog实现的标准化名称。 请注意,类型为After=的依赖项仅定义了建议的顺序,但实际上并不会在abrtd启动时导致syslog启动,因为即使没有syslog, abrtd实际上也可以正常工作。 然而,如果两者都启动了(通常是这样),那么它们的顺序由这个依赖项控制。

一些systemd中的特殊目标 可以参考 man 7 systemd.special

[Service]部分包含关于服务本身的信息。全部是应用于service的设置,而不包括systemd维护的其他类型的单元(mount points, devices, timers等)。 这里使用了两种设置:ExecStart= 获取要在服务启动时执行的二进制文件的路径。Type= 配置服务如何通知init系统它已经启动完毕。 由于传统的Unix守护进程在fork结束并初始化后台守护进程后会返回父进程,因此我们在这里将类型设置为forking。 告诉systemd等待启动的二进制程序返回,然后考虑在守护进程之后仍在运行的进程。

[install]部分包含有关建议的安装情况,即在什么情况下以及通过哪些触发器启动服务。在这种情况下,我们简单地说,该服务应在multi-user.target时启动。 这也是一个特殊的unit,近似与经典的SysV Runlevel 3的定位。设置WantedBy=对运行中的守护进程几乎没有影响。它主要是给systemctl enable命令读取, 以实现service自启动(在对应的target上)。

将此文件移动到 /etc/systemd/system/lib/systemd/system 路径下,并执行 systemctl daemon-reload 更新。 之后可以对该service执行相关systemctl的控制命令,systemctl start , systemctl stop , systemctl status , systemctl enable 等。

更新的版本

1
2
3
4
5
6
7
8
9
10
11
[Unit]
Description=ABRT Automated Bug Reporting Tool
After=syslog.target

[Service]
Type=dbus
BusName=com.redhat.abrt
ExecStart=/usr/sbin/abrtd -d -s

[Install]
WantedBy=multi-user.target

这里主要修改了 Type= 的类型为 dbus ,并配置了该服务使用的dbus的名称 BusName经典的SysV服务启动后,通常fork两次,并从终端分离,当通过脚本启动服务时,这要做是有用有必要的, 但如果使用systemd来管理守护进程时,那么就不需要这么做了,没有必要且启动慢。

原因是被fork的守护进程通常与systemd启动的原始进程没有什么关系,因此在fork结束后,systemd很难弄清楚属于服务的哪个进程实际上是有效主进程, 哪些进程可能只是辅助进程。但是这些信息对守护进程管理方systemd来说又是非常重要的,如监控进程,异常终止时自动重启,收集崩溃信息和进程退出码等。

为了让systemd更容易找到守护进程的主进程,这里更新时将类型改为 dbus ,该类型的使用情况是 服务程序初始化的最后一步是从系统的D-Bus总线上 获取一个名称。因为这里的 abrtd 程序是这样做的,所以可以使用该类型。在该类型下,systemd会创建abrtd进程,并不需要fork(由启动参数的-d -s) 实现。只要com.redhat.abrt这个名称出现在DBus总线上,systemd就认为服务已启动成功。这样,systemd生成的进程就是守护进程的主进程, systemd有一种可靠的方法来确定守护进程何时完全启动,systemd可以轻松地监督它。

D-Bus : dbus 是linux上由内核和应用层实现的一套IPC机制,具有低延迟,低开销,高可用的特点。 systemd 是支持使用dbus,不是systemd实现了dbus。参考DBUS基础知识

以上就是一个基本的service服务了,还可以使用更多的参数设置,如设置Restart=配置如何重启;设置OOMScoreAdjust= 配置内核在OOM时保留这个进程; 还可以配置使用的资源限制等,比较多。详细参考,有大部分配置说明。

  • systemd.unit(5)
  • systemd.service(5)
  • systemd.exec(5)
This post is licensed under CC BY 4.0 by the author.