Systemd编写服务管理脚本
# systemd
编写服务管理脚本
# Unit(单元)的配置文件
Unit 是 systemd
进行任务管理的基本单位。我们在前文中已经介绍过,service 类型的 unit
代表一个后台服务进程。接下来我们详细介绍如何配置 service 类型的 unit。下面是一个简单的服务配置:
[Unit]
Description=Prometheus Server
Documentation=https://prometheus.io/docs/introduction/overview/
After=network.target
[Service]
User=prometheus
Restart=on-failure
WorkingDirectory=/usr/local/share/prometheus/
ExecStart=/usr/local/share/prometheus/prometheus \
-config.file=/usr/local/share/prometheus/prometheus.yml
[Install]
WantedBy=multi-user.target
2
3
4
5
6
7
8
9
10
11
12
13
14
这是 Prometheus 服务的配置文件。将上述内容保存到文件 /lib/systemd/system/prometheus.service
中,然后就可以使用 systemctl
命令管理 Prometheus 服务了。注意,服务类型的配置文件名称必须以 .service
结尾。
查看上面配置信息的详细内容,我们会发现整个配置分为三个部分:
- [Unit]:
unit
本身的说明,以及与其它有依赖关系的服务的设置,包括在什么服务之后才启动此unit
。 - [Service]: 不同的
unit
类型需要使用相对应的设置项目,服务类型的unit
就是 [Service],这个项目主要规范服务启动的脚本、环境配置文件名、重新启动的方式等等。 - [Install]: 这个部分主要设置该
unit
安装到哪个 target。
# 服务类型 unit
的详细配置
配置文件分为三个部分,每个部分都可以提供详细的配置信息。为了精确控制服务的运行方式,我们需要了解这些详细的配置选项,并让服务以期望的方式运行。
# [Unit] 部分
- Description: 关于该
unit
的简易说明。 - Documentation: 文档相关内容,如
Documentation=https://prometheus.io/docs/introduction/overview/
。 - After: 说明本
unit
是在哪个服务启动后才启动,仅说明服务启动顺序,并没有强制要求。 - Before: 与 After 相反,指定的服务启动前最好启动本服务。
- Requires: 本
unit
需要在某个服务启动后才能启动,设置服务间的依赖性。 - Wants: 与 Requires 相反,规范的是本
unit
之后还要启动哪些服务,如果设置的服务未启动成功,不会影响本unit
。 - Conflicts: 这个项目后面接的服务如果已启动,则本
unit
无法启动,反之亦然。
# [Service] 部分
Type: 说明服务的启动方式,会影响到
ExecStart
,主要有以下几种类型:simple
: 默认值,由ExecStart
设置的程序来启动,启动后常驻于内存中。forking
: 由ExecStart
指定的启动程序通过spawns
产生子进程提供服务,然后父进程退出。oneshot
: 与simple
类似,但程序工作完毕后即结束,不会常驻内存。dbus
: 与simple
类似,但需在取得一个 D-Bus 名称后,才继续运行。idle
: 与simple
类似,意思是要执行此服务必须在所有工作顺利执行完毕后才执行。notify
: 与simple
类似,但需收到一个sd_notify()
函数发送的消息后,才会继续运行。
ExecStart: 实际执行此服务的程序,接受 "命令 参数 参数..." 的格式,不能接受特殊字符,许多 bash 语法也不支持。
ExecStartPre 和 ExecStartPost: 分别在服务启动前后,执行额外的命令。
ExecStop: 用来实现
systemctl stop
命令,关闭服务。ExecReload: 用来实现
systemctl reload
命令,重新加载服务的配置信息。Restart: 设置为
Restart=1
时,如果服务终止,会自动重启服务。RestartSec: 与
Restart
配合使用,设置服务终止多长时间后重新启动,默认是 100ms。KillMode: 可以是
process
,control-group
,none
之一。TimeoutSec: 设置服务启动或关闭时的超时时间。
RemainAfterExit: 当设置为
RemainAfterExit=1
时,服务所属的所有程序都终止后,会尝试重新启动。Environment: 用来设置环境变量,可以多次使用。
EnvironmentFile: 通过文件方式设置环境变量,指定文件路径,内容格式类似
KEY=VALUE
。
# [Install] 部分
- WantedBy: 设置
unit
附挂在哪个target
unit
下面。 - Also: 当前
unit
被 enable 时,Also 后面接的unit
也要 enable。 - Alias: 当
systemctl enable
相关服务时,此服务会进行链接文件的创建。
# Timer 类型 unit
的详细配置
Timer 类型的 unit
主要用来执行定时任务,有可能取代 cron
服务。与服务类型的 unit
不同,timer unit
配置文件中的主要部分是 [Timer]。
- OnActiveSec: 当
timers.target
启动后多久执行此unit
。 - OnBootSec: 当开机后多久执行此
unit
。 - OnStartupSec: 当
systemd
第一次启动后多久执行此unit
。 - OnUnitActiveSec: 管理的服务最后一次启动后,隔多久再执行一次。
- OnUnitInactiveSec: 管理的服务最后一次停止后,隔多久再执行一次。
- Unit: 一般不需要设置,若服务名称和
timer
名称不相同,则在.timer
文件中通过Unit
项指定服务名称。 - OnCalendar: 使用实际时间(非循环时间)的方式来启动服务。
- Persistent: 当使用
OnCalendar
设置时,指定该功能是否持续执行。
# 配置 Redis 服务
在 Ubuntu 上,我们一般会手动编译并安装 Redis。在安装完成后需要将 Redis 配置为 systemd
管理的服务,具体配置过程如下:
# 添加 Redis 配置文件
首先手动创建 /etc/redis
目录并添加配置文件:
$ sudo mkdir /etc/redis
然后将 Redis 配置文件 redis.conf
拷贝到 /etc/redis
目录中:
$ sudo cp /tmp/redis-4.0.0/redis.conf /etc/redis/
修改配置文件 /etc/redis/redis.conf
中的 supervised
为 systemd
:
supervised systemd
继续修改配置文件 /etc/redis/redis.conf
中的工作目录:
dir /var/lib/redis
# 配置由 systemd
管理的 Redis 服务
创建 /etc/systemd/system/redis.service
文件:
$ sudo vim /etc/systemd/system/redis.service
编辑其内容如下:
[Unit]
Description=Redis In-Memory Data Store
After=network.target
[Service]
User=redis
Group=redis
ExecStart=/usr/local/bin/redis-server /etc/redis/redis.conf
ExecStop=/usr/local/bin/redis-cli shutdown
Restart=always
[Install]
WantedBy=multi-user.target
2
3
4
5
6
7
8
9
10
11
12
13
启动服务并配置为开机启动:
$ sudo systemctl start redis
$ sudo systemctl enable redis
$ sudo systemctl status redis
2
3
# 通过脚本定时备份文件
备份文件的 bash 脚本:
#!/bin/bash
mydate()
{
date "+%Y%m%d%H%M%S"
}
backupdate=$(mydate)
tar -zcf /tmp/backup.${backupdate}.tar.gz /home/nick/learn
2
3
4
5
6
7
将上述代码保存到 /usr/local/bin/backupdir.sh
文件,并添加可执行权限:
$ sudo chmod +x /usr/local/bin/backupdir.sh
然后创建 service unit
配置文件:
[Unit]
Description=nick backup learn dir service
[Service]
User=nick
Group=nick
Type=simple
ExecStart=/usr/local/bin/backupdir.sh
[Install]
WantedBy=multi-user.target
2
3
4
5
6
7
8
9
10
11
将上述 unit
配置保存到 `/etc/systemd/system
/nickbak.service` 文件中。然后执行以下命令测试服务执行情况:
$ sudo systemctl daemon-reload
$ sudo systemctl start nickbak.service
2
这样的备份任务只会在执行 sudo systemctl start nickbak.service
时执行一次。下面我们通过 timer
unit
将其配置为定时执行。
# 创建 Timer unit
配置文件
[Unit]
Description=nick backup learn dir timer
[Timer]
OnCalendar=*:0/15
Persistent=true
Unit=nickbak.service
[Install]
WantedBy=multi-user.target
2
3
4
5
6
7
8
9
10
将上述 unit
配置保存到 /etc/systemd/system/nickbak.timer
文件中。配置中的 OnCalendar=*:0/15
表示每 15 分钟执行一次 nickbak.service
服务。
执行以下命令将 nickbak.timer
设置为开机启动,并启动 nickbak.timer
:
$ sudo systemctl daemon-reload
$ sudo systemctl enable nickbak.timer
$ sudo systemctl start nickbak.timer
2
3
查看 nickbak.timer
的状态:
$ sudo systemctl status nickbak.timer
从现在开始 nickbak.timer
会每隔 15 分钟执行一次 nickbak.service
服务。
# 总结
systemd
提供了服务管理(实际上是 unit
管理)的各个方面。我们需要做的就是编写好服务 unit
的配置文件,然后利用 systemd
来管理我们的服务。这是一个看似简单但实际复杂的任务,很多配置项需要在实践中不断调整和优化。希望本文对大家来说是一个简单的入门。
- 01
- GPT分区使用 parted 扩展分区的操作流程 原创08-28
- 02
- VictoriaMetrics 集群版安装与配置 原创08-24
- 03
- Kubernetes (k8s) 相关名词详解 原创06-27