我有一个非常简单的 SysVinit 服务/etc/rc.d
:
#!/bin/bash
PIDFILE="/var/run/test.pid"
status() {
if [ -f "$PIDFILE" ]; then
echo 'Service running'
return 1
fi
return 0
}
start() {
if [ -f "$PIDFILE" ] && kill -0 "$(cat "$PIDFILE")"; then
echo 'Service already running'
return 1
fi
echo 'Starting...'
test & echo $! > "$PIDFILE"
return 0
}
stop() {
if [ ! -f "$PIDFILE" ] || ! kill -0 "$(cat "$PIDFILE")"; then
echo 'Service not running'
return 1
fi
echo 'Stopping...'
kill -15 "$(cat "$PIDFILE")" && rm -f "$PIDFILE"
return 0
}
case "$1" in
start)
start
;;
stop)
stop
;;
status)
status
;;
restart)
stop
start
;;
*)
echo "Usage: $0 {start|stop|restart}"
exit 1
esac
当系统启动时,它会启动服务。
但是当系统停止时,它永远不会调用停止命令。我能想到的唯一原因是系统认为该服务未运行或未正确启动。
但是这样做有什么要求呢?
- 您是否需要为启动命令返回一个特殊的退出代码?
- 我需要创建一个文件来
/var/lock/subsys
表明它是活动的吗? - 还有什么可能导致系统认为服务没有启动?
看起来 Synology 从经典的 SysVinit 转移到
upstart
DSM 6 左右,然后转移到systemd
DSM 7。这两个初始化系统都为经典的 SysVinit 风格的启动/停止脚本提供向后兼容性,但您应该注意一些怪癖。如果您有 DSM 7.0 或更新版本,那么在安装脚本后您可能应该运行
systemctl daemon-reload
,因此systemd-sysv-generator
应该自动.service
为它创建一个文件(可能在 中/run/systemd
)。然后你可以用systemctl start <script name>
- 开始你的脚本,实际上应该这样做,而不是仅仅手动运行脚本。只有当它实际执行了相应的启动作业时systemd
,才会意识到需要运行作业。<your script> stop
这是因为在启动时
systemd
会将每个服务设置为单独的进程控制组(管理员手动运行启动脚本不会这样做)。这是服务本身完全不可见的东西(除非他们专门去寻找它),并且服务的任何子进程都将继承此控制组成员身份。如果控制组中没有进程,它将自动不复存在。
关闭时,
systemd
将只遍历现有的控制组,并对它找到的任何非默认控制组运行停止命令。任何在没有使用的情况下启动的服务systemctl start
都将成为“管理员的交互式会话”控制组的一部分,而不是“服务 X”控制组的一部分,并且实际上将在不运行相应的停止脚本的情况下被杀死。如果您需要在服务因某种原因终止时自动重启等功能,您应该考虑为适用的初始化系统使用适当的“本机”配置方法:
/etc/init/*
Synology DSM 6.x 系列中 Upstart 的文件/etc/systemd/system/*.service
Synology DSM 7.x 系列及更新版本中 systemd 的文件。这些 init 系统具有内置的自动重启功能,您只需进行一些配置即可使用,而不必自己编写包装脚本来监视您的服务进程。Synology DSM 7 开发者指南
Synology DSM 6 开发者指南
有关为 DSM 6 和 7 配置服务的可能有用的说明