Linux 服务创建 (Systemd Service)

什么是服务?有什么用?

Linux下面的服务可以理解为和Windows上的,也可以理解为一种守护(Daemon)进程,通常是在后台默默运行的基础设施应用,如数据库、驱动等。

通过创建服务,我们可以将自己的应用设为开机启动,并可以自动重启。

本文参考了How to create a systemd service in Linux,基本上就是翻译了他。

服务配置文件 (Systemd Service File)

Debian中以.service文件形式储存在/etc/systemd/system中

一个常见的服务配置文件如下,可见其由”Unit”、”Service”、”Install”三部分组成,

1
2
3
4
5
6
7
8
9
10
11
12
13
14
[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

Unit 部分

这部分记录了服务的基本信息,有以下常用部分:

  • Description
    给人看的描述
  • Wants
    这个服务需要依赖与某个服务,如xxx.service。
  • Requires
    同上,但本项的服务如果依赖不存在或者失败则会不运行(也就是上面的Wants就是嘴上说说)。
  • After
    在什么阶段之后运行,通常是xxx.target,比如开启后运行就是multi-user.target,关机就是poweroff.target,要求有网络就是network.target等。
  • Before
    在什么服务之前运行,基本同上。

Service 部分

这部分记录了本服务应该如何运行,有以下常用部分:

  • ExecStart
    这个服务运行程序的命令,比如执行一下apt更新就写apt update
  • ExecReload
    少见。使用systemctl restart等命令时执行的重启命令,如果你的服务重启需要特定的命令,或者是一些操作储存数据的服务,你需要使用该项优雅地重启。
  • Type
    服务进程的类型,通常使用simple,当然还有exec、forking之类的。像nginx这种有一个短暂的中间父进程运营应用的,必须设置为forking否则systemd会认为运行失败。详见最后面的Type介绍节。
  • Restart
    少见。服务重启的时机,可以是关闭no或者几种异常情况on-failureon-abnormal等。

Install 部分

这部分决定了使用systemctl enablesystemctl disable启动和关闭服务的处理,有以下常用部分:

  • WantedBy
    和 Unit 段的 Wants 作用相似,填写的内容类似于Unit部分After和Before中的各种target,只有后面列出的不是服务所依赖的模块,而是依赖当前服务的模块,当前 Unit 激活时(enable)符号链接会放入 /etc/systemd/system目录下面以<Target名>+.wants后缀构成的子目录中。
  • RequiredBy
    和 Unit 段的 Requires作用相似,同上,当前 Unit 激活时,符号链接会放入 /etc/systemd/system目录下面以<Target 名>+.required后缀构成的子目录中。
  • Also
    当前 Unit enable/disable 时,同时 enable/disable 的其他 Unit。
  • Alias
    当前 Unit 可用于启动的别名。

WantedBy、RequiredBy:在 .wants/ 或 .requires/ 子目录中为服务建立相应的链接。这样做的效果是当列表中的服务启动,本服务也会启动。

要实现开机启动,在Unit中写After或者在Install中写WantedBy都是可以的。

服务安装、运行

和Windows一样,服务的运行也是分用户的,Linux里的服务也分为Root用户运行和其他用户运行,区别只是服务配置文件的“存放”的位置。

Root用户运行的服务,配置讲上一章节写的xxx.service文件存放到/etc/systemd/system/,使用其他用户运行的服务,文件存放到~/.config/systemd/user/,你可能需要手动创建这个目录。

文件存放到位后,不重启系统则需要使用systemctl daemon-reloadsystemctl --user daemon-reload刷新配置文件,后者是其他用户运行服务时使用的。

后面安装、运行等非Root用户服务操作都添加--user参数

直接systemctl enable xxx.service即可安装、启动,通过is-enabled可以查看是否被安装,然后就是常规的startstoprestart命令,这里略过。

服务运行类型 Service Type

在配置文件的[Service]部分中的Type,常用的几个简单介绍如下:

Type 介绍
oneshot 适合运行一次、短暂立刻退出的服务,可能需要同时设置 RemainAfterExit=yes 使得 systemd 在服务进程退出之后仍然认为服务处于激活状态。
simple 立刻普通地启动程序。
idle 基本等于simple,但是等待其他服务启动、处理都完成了,相当于让位,也避免启动日志混在一起。
notify 基本等于simple,但在就绪后向systemd发送一个信号
forking 如果运行的程序有个短暂的中间父进程,或者说调用了fork(),父进程退出后应该视为正常,则使用此类型,应同时指定 PIDFile=,以便 systemd 能够跟踪服务的主进程。

详细文档请看该链接

简单例子

nginx

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
[Unit]
Description=nginx - high performance web server
#描述服务
After=network.target remote-fs.target nss-lookup.target
#描述服务类别

[Service]
Type=forking
#后台运行的形式
PIDFile=/usr/local/nginx/logs/nginx.pid
#PID文件的路径
ExecStartPre=/usr/local/nginx/sbin/nginx -t -c /usr/local/nginx/conf/nginx.conf
#启动前准备 校验配置文件是否错误
ExecStart=/usr/local/nginx/sbin/nginx -c /usr/local/nginx/conf/nginx.conf
#启动命令 指定配置文件
ExecReload=/usr/local/nginx/sbin/nginx -s reload
#重启命令
ExecStop=/usr/local/nginx/sbin/nginx -s stop
#停止命令
ExecQuit=/usr/local/nginx/sbin/nginx -s quit
#强制停止
PrivateTmp=true
#给服务分配临时空间

[Install]
WantedBy=multi-user.target

开机时运行一个脚本

1
2
3
4
5
6
7
8
9
10
[Unit]
Description = Run script after system booted.
# 要求脚本具有可执行权限
ConditionFileIsExecutable=/usr/bin/script.sh

[Service]
ExecStart = /usr/bin/script.sh

[Install]
WantedBy = multi-user.target

See Also

推荐看看 https://www.junmajinlong.com/linux/index/#systemd


Linux 服务创建 (Systemd Service)
https://sodacooky.netlify.app/2023/Linux_Systemd_Service/
作者
Sodacooky
发布于
2023年6月1日
许可协议