使用systemd来构建你的服务

24次阅读

共计 2612 个字符,预计需要花费 7 分钟才能阅读完成。

systemd 是什么
Systemd 服务是一种以 .service 结尾的单元(unit)配置文件,用于控制由 Systemd 控制或监视的进程。简单说,用于后台以守护精灵(daemon)的形式运行程序。
为什么要使用 systemd

service 文件编写简单易用
可以自动维持进程存活(强大的功能,可以取代 PM2)
自动收集进程输出的输出

systemd 主要命令
可以看到 systemd 以字母 d 结尾,根据 linux 惯用规则,可以判断该进程为守护进程,可以通过 systemctl 与之交互。
systemctl start redis.service #启动服务
systemctl stop redis.service #停止服务
systemctl restart redis.service #重启服务
systemctl enable redis.service #将 redis 设置为开机启动
编写 systemd
systmd service 文件一般放在 /etc/systemd/system/ 文件夹中。
systemd service 文件是结构化的,以下给出一份笔者常用的清单。
[Unit]
Description=Git Auto Update Hook Service
After=network.target

[Service]
Type=simple
ExecStart=/root/src/git-hookd/git-hookd
Restart=always
[Install]
WantedBy=multi-user.target
拿之前写过的 init.d 的脚本对比一下
#!/bin/bash
### BEGIN INIT INFO
# Provides: xialeistudio
# Required-Start: $network
# Required-Stop: $local_fs
# Default-Start: 2 3 4 5
# Default-Stop: 0 1 6
# Short-Description: test service
# Description: test service
### END INIT INFO
PROG=”testd”
PROG_PATH=”/root/apps/testd”
PROG_ARGS=”-u xialei”
PID_PATH=”/var/run/”

start() {
if [-e “$PID_PATH/$PROG.pid”]; then
echo “Error! $PROG is running!” 2>&1
exit 1
else
$PROG_PATH/$PROG $PROG_ARGS 2>&1 > “/var/log/$PROG.log” &
pid=`ps ax|grep testd|awk ‘{print $2}’|head -n 1`
echo “$PROG started”
echo $pid > “$PID_PATH/$PROG.pid”
fi
}

stop() {
if [-e “$PID_PATH/$PROG.pid”]; then
pid=`ps ax|grep testd|awk ‘{print $2}’|head -n 1`
kill $pid

rm -rf “$PID_PATH/$PROG.pid”
echo “$PROG $pid killed”
else
echo “Error! $PROG not running!” 2>&1
exit 1
fi
}

if [“$(id -u)” != “0” ]; then
echo “Please run as root!” 2>&1
exit 1
fi

case “$1” in
start)
start
exit 0
;;
stop)
stop
exit 0
;;
reload|restart)
stop
start
exit 0
;;
**)
echo “Usage: $0 {start|stop|reload}” 2>&1
exit 1
;;
esac
可以看到 init.d 脚本实在是太原始了,systemd 取代 init.d 指日可待
systemd service 文件说明
service 文件由 Unit, Service, Install 三部分组成
Unit
所有引导过程中 systemd 要控制的文件 / 设备 / 程序等等都称为一个单元。

Description: 服务描述
Wants: 本单元启动成功,则会启动此字段定义的单元,如果 Wants 定义的单元启动失败,对本单元无影响
Requires:本单元启动成功,则会启动此字段定义的单元,如果 Requires 定义的单元启动失败,本单元也失败。该字段无法控制先后顺序,如果 Requires 定义的单元未启动完成就启动本单元,那么一个都启动不了,不建议用这个字段
OnFailure:本单元如果启动失败,则启动该字段定义的单元
Before/After:指定本单元的启动顺序

本例中只需要依赖网络单元即可
Service
服务本体定义:

Type 启动类型
ExecStart 启动服务的命令
ExecStop 停止服务的命令(一般不写)
Restart 重启规则
RemainAfterExit 即使没有进程,也任务服务启动成功

Type 启动类型有以下几种:
+ simple:默认类型,启动的进程将成为服务进程。
+ forking:标准 Unix Daemon 进程。本进程启动后会通过系统调用 fork,把必要的通信频道都设置好之后父进程退出,留下守护精灵的子进程。(也就是说你自己来将进程变成 daemon 进程)
+ oneshot:一次性命令。该服务运行完毕后没有进程,所以需要配合 RemainAfterExit。

Restart 重启规则有以下几种:
+ no(默认值):退出后不会重启
+ always:不管是什么退出原因,总是重启
+ on-success:只有正常退出时(退出状态码为 0),才会重启
+ on-failure:非正常退出时(退出状态码非 0),包括被信号终止和超时,才会重启
+ on-abnormal:只有被信号终止和超时,才会重启
+ on-abort:只有在收到没有捕捉到的信号终止时,才会重启
+ on-watchdog:超时退出,才会重启

Install
systemd 装载规则定义

WantedBy 将被谁装载,本例中使用 multi-user.target,最终服务将通过软链接到 /etc/systemd/system/multi-user.target.wants 目录
Alias 服务别名,可以通过 systemctl 服务别名 restart 之类的来操作

写在最后
是时候通过 systemd 改写 init.d 的服务了,有必要的话可以连 pm2 守护的进程都交给 systemd 来处理。

正文完
 0