在Linux中如何创建自定义的systemd服务的步骤
1.systemd 服务文件的基本结构
systemd
服务文件包含三个重要且必要的配置部分,分别是[Unit]、[Service]和[Install]部分。这类文件以**.service**作为扩展名,并使用井号(#)添加单行注释。
以下是一个systemd
服务文件的示例:
[Unit]
Description=Apache web server
After=network.target
Before=nextcloud-web.service[Service]
ExecStart=/usr/local/apache2/bin/httpd -D FOREGROUND -k start
ExecReload=/usr/local/apache2/bin/httpd -k graceful
Type=notify
Restart=always[Install]
WantedBy=default.target
RequiredBy=network.target
下面解释每一部分的含义。
1.1[Unit]部分
Unit部分用于定义服务单元本身的元信息和描述。具体包含:服务描述文本、依赖关系等配置项。
该段主要字段说明:
-
Description:服务的可读性描述文本
-
After:定义服务启动顺序依赖。例如配置Apache服务时,通常需指定其在network.target之后启动(即网络就绪后再启动Web服务)
-
Before:定义当前服务需在指定服务之前启动。例如示例中要求"Nextcloud服务启动前必须确保Apache已运行",这是因为Nextcloud依赖Apache服务。与After类似,可指定target或其他服务
1.2[Service]部分
Service部分定义服务的启动、终止等运行时行为。
该段核心字段说明:
-
ExecStart:服务启动时执行的命令(示例中为启动Apache服务)
-
ExecReload(可选):定义服务重启机制。对于涉及磁盘I/O(特别是数据库类服务),建议配置优雅终止方式
-
Type:定义进程启动类型,可选值包括: simple(默认值)、exec、forking、oneshot、dbus、notify、idle
-
Restart(推荐配置):定义服务异常退出时的重启策略,可选值包括: no(不重启)、on-success、on-failure、on-abnormal、on-watchdog、on-abort、always
1.3[Install]部分
Install部分定义服务安装行为(即通过systemctl enable/disable
启用/禁用服务时的配置)。
该段关键字段:
-
WantedBy:指定系统运行级别(runlevels)关联。例如:
-
default.target
表示系统初始化完成后(用户登录阶段) -
图形界面服务通常关联
graphical.target
-
-
RequiredBy:与WantedBy类似,但建立的是强依赖关系(依赖项不满足时将导致服务启动失败)
2.创建自定义的 systemd 服务
下面我们分别创建两个 systemd 服务,一个需要超级用户权限,另一个以普通用户身份执行。
二者的区别是 root 用户执行的服务与普通用户执行的服务 systemd 服务文件的位置不同。
2.1 创建root 用户的 systemd 服务
下面是自己编写的一个名为 sys-update.sh
的脚本,现在希望以 root
用户在系统启动时自动运行。该脚本的绝对路径是 /root/.scripts/sys-update.sh
。以下是脚本内容:
#!/usr/bin/env bashif [ ${EUID} -ne 0 ]
thenexit 1 # this is meant to be run as root
fiapt-get update 1>/dev/null 2>>/root/logs/sys-update.log
这个脚本的功能是这样的,首先,它会检查当前用户是否为root用户,如果是 root 用户,就会执行apt-get update
命令,该命令输出的所有错误信息将被追加到/root/logs/sys-update.log
文件中,而其他输出则会被重定向到/dev/null
文件。
1)创建systemd服务文件
接下来我们为这个脚本创建 systemd
服务文件。但在开始之前,需要了解需要超级用户权限的"systemd服务文件"应该放在什么位置。
通常最佳实践是将这些systemd
服务文件放置在/etc/systemd/system/
目录下。
因此,我将创建一个名为update-on-boot.service
的文件,其完整路径为/etc/systemd/system/update-on-boot.service
。
下同是这个文件的内容:
[Unit]
Description=Keeping my sources fresher than Arch Linux
After=multi-user.target[Service]
ExecStart=/usr/bin/bash /root/.scripts/sys-update.sh
Type=simple[Install]
WantedBy=multi-user.target
这是一个非常简单的 systemd
服务文件。它所做的只是使用 bash
解释器来解释/root/.script/sys-update.sh
脚本并执行它。
2)启用服务
首先重新加载systemd
守护进程配置,这样使刚才新创建(修改)的systemd
配置立即生效:
sudo systemctl daemon-reload
接着启用我们自定义的 systemd
服务,它的语法如下:
sudo systemctl enable SERVICE-NAME.service
这样,我们就可以这样启动前面定义的systemd服务:
sudo systemctl enable update-on-boot.service
该服务是否启用成功,可以用下面语法进行检查:
sudo systemctl is-enabled SERVICE-NAME.service
$ sudo systemctl is-enabled update-on-boot.service
enabled
2.2创建普通用户的 systemd 服务
前面的例子是服务在系统启动时启动,下面我们创建一个打算在关闭之前运行的脚本。
这个脚本的文件名为big-uptime.sh
,它的完整路径是/home/pratham/.scripts/big-uptime.sh
,以下是它的内容:
#!/usr/bin/env bashuptime | tee -a /home/pratham/logs/uptime.log
这个脚本的功能是将系统运行时间记录到/home/pratham/logs/uptime.log
文件中,相当于一个方便的计时器!
1)创建systemd服务文件
现在我们来为它创建一个systemd服务文件,但在开始之前,需要了解普通用户的systemd
服务文件**(unit文件**)应该存放在哪里。普通用户的systemd服务文件应该放在~/.config/systemd/user/
目录下。
通常情况下,~/.config/systemd/user/
目录并不存在,所以需要先创建这个目录。可以使用以下命令创建:
mkdir -p ~/.config/systemd/user
以下是什么pratham
用户的systemd
服务文件的内容:
[Unit]
Description=Log uptime in scoreboard
DefaultDependencies=no
Before=shutdown.target[Service]
Type=oneshot
ExecStart=/usr/bin/bash /home/pratham/.scripts/big-uptime.sh
TimeoutStartSec=0[Install]
WantedBy=shutdown.target
这个systemd
服务文件与之前的有几个关键区别:
其中最重要的是它的Type被设置为"oneshot"。
当Type=oneshot
时,systemd
会确保在所有服务启动/停止过程中,必须等待当前服务完全初始化或启动完成后才会继续执行其他服务。
现在把这个systemd
服务文件保存为~/.config/systemd/user/scoreboard.service
。
2)启用服务
首先,重新加载systemd
:
systemctl --user daemon-reload
然后,启用该自定义的systemd
服务:
systemctl --user enable scoreboard.service
同样,最后检查服务的状态:
$ systemctl --user is-enabled scoreboard.service
enabled