我有一个脚本,我想在机器关闭或重新启动之前执行它,但它只用参数触发start
,而不是用参数触发stop
,这让我发疯。
我的系统上存在以下符号链接:
/etc/rc0.d/K01init.sh
/etc/rc1.d/K01init.sh
/etc/rc2.d/S99init.sh
/etc/rc3.d/S99init.sh
/etc/rc4.d/S99init.sh
/etc/rc5.d/S99init.sh
/etc/rc6.d/K01init.sh
都指向同一个脚本/etc/init.d/init.sh。基于另一个线程,我也尝试过不使用.sh
后缀,这没有改变任何内容。
/etc/init.d/init.sh
#!/bin/sh
### BEGIN INIT INFO
# Provides: init.sh
# Required-Start: $all
# Required-Stop:
# Default-Start: 2 3 4 5
# Default-Stop: 0 1 6
# Short-Description: xxx
# Description: xxx
### END INIT INFO
if [ "$1" = "start" ]; then
echo "log message"
//do stuff
fi
echo "$1"
if [ "$1" = "stop" ]; then
echo "log message"
//do stuff
fi
exit 0
stop
该脚本在启动期间运行良好,但抱怨未执行应在块中进行的清理。当我回显$1
日志时,它仅且始终显示start
,这意味着操作系统显然从未将stop
命令发送到我的脚本。从命令行()运行脚本就像带有和参数sudo /etc/init.d/init.sh stop
的魅力一样,所以我很困惑为什么当我停止机器时它不起作用。start
stop
我这里哪里出错了?我正在运行 Ubuntu 18.04,当前的运行级别是 5(但这应该不相关,因为这里应该是 0 和 6 左右)。有趣的是,我尝试通过添加到脚本来检查执行时的实际运行级别echo "$(who -r)"
,该脚本不会向日志输出任何内容!
如果相关:我正在谈论通过sudo reboot
/重新启动sudo systemctl reboot
和通过Azure GUI(它是虚拟机),不确定Azure的重启机制是否不同,但这两种方法都不起作用。
答案1
您应该了解 systemd,它已经取代了旧的运行级别和 init 系统。
systemd 仍然可以运行旧的 init.d 脚本,但我建议您学习一些 systemd 并编写一个 systemd 服务文件。首先看这里systemd 如何使用 /etc/init.d 脚本?,您可以在其中找到有关 systemd 处理 init.d 的一些描述。
我的猜测是您的脚本在关闭时不会执行,因为 systemd 不认为它正在运行。也许您的脚本是执行然后退出的东西。它不会一直运行。 systemd 检测到这一点并且脚本未处于运行状态。如果存在,则不运行。因此,systemd 不会阻止它,因为没有什么可以阻止。
使用 systemctl 命令检查状态并查看有关您的服务的信息。您只需输入systemctl
并查找脚本即可。你也可以尝试
systemctl status init.sh
systemctl start init.sh
systemctl stop init.sh
systemctl restart init.sh
这些是实际执行的命令,而不是旧的 init.d 脚本。
我建议迁移到 systemd。查看服务单元配置(https://www.freedesktop.org/software/systemd/man/systemd.service.html)。也许您最好的服务类型是oneshot
。你可以在这里找到一个例子如何在关机前使用 systemd 运行脚本?。根据 examplelpe,您应该创建如下内容/etc/systemd/system/init.sh.service
:
[Unit]
Description=init.sh
[Service]
Type=oneshot
RemainAfterExit=true
ExecStart=/etc/init.d/init.sh start
ExecStop=/etc/init.d/init.sh stop
[Install]
WantedBy=multi-user.target
然后在 systemd 中启用您的服务:
sudo systemctl enable init.sh.service
如果你想更精确地控制你的服务何时启动,你可以添加After=
, Before=
。还有很多其他选择。
答案2
Required-Stop:
我怀疑问题在于缺乏价值。你告诉它,当你停止时,你不需要运行任何其他东西,比如记录器和磁盘。添加参数以匹配该Required-Start:
行。
您的名字也应该更具描述性。有一个标准服务“init”——它是将运行脚本的事物的父级。