我正在设置 Debian,使其在 kiosk 模式下工作。为此,我创建了一个执行看门狗功能的服务:
[Unit]
Description=Watchdog for myapp
[email protected]
After=polkit.service
After=udisks2.service
[Service]
ExecStartPre=systemctl stop dm
ExecStart=su user -c "startx /opt/myapp-watchdog.sh -- :0 vt7"
ExecStop=systemctl start dm
Type=simple
Restart=on-failure
StartLimitInterval=60s
StartLimitBurst=5
RuntimeMaxSec=infinity
Environment="DISPLAY=:0"
Environment="XAUTHORITY=/home/user/.Xauthority"
Environment="XDG_VTNR=7"
[Install]
WantedBy=graphical.target
问题是 ExecStart 不是从 myapp 获取退出代码,而是从 startx 获取退出代码。我尝试了很多选择,但我无法想出一种可以正常工作的方法......
我尝试尝试通过管道传递退出代码, exit &?并将退出代码写入文件。但是,显然,我的 bash 技能不足以发出正确的命令。
谷歌搜索也没有帮助,因为找到人们直接从根开始调用的情况,而不是从用户开始,这就是为什么退出代码的传输比我的情况容易得多
答案1
弄清楚了。通过startx的方式是无法解决这个问题的(证明:链接到 gitlab 上的 xserver 错误)。我必须发明自行车并使用拐杖。
解决方案是让服务运行一个脚本,在该脚本中软件循环运行。之后,检查软件退出代码。如果代码为 0,则脚本完成其工作。否则,开始循环的下一次迭代。下面的代码实现了一种机制,如果软件在第一次紧急退出后的最后一分钟内错误完成 5 次或更多次,则退出此循环。
服务代码:
[Unit]
Description=Watchdog for myapp
[email protected]
After=polkit.service
After=udisks2.service
[Service]
ExecStartPre=systemctl stop dm
ExecStart=su user -c "startx /opt/myapp-watchdog.sh -- :0 vt7"
ExecStop=systemctl start dm
Type=simple
Restart=on-failure
StartLimitInterval=60s
StartLimitBurst=5
RuntimeMaxSec=infinity
Environment="DISPLAY=:0"
Environment="XAUTHORITY=/home/user/.Xauthority"
Environment="XDG_VTNR=7"
[Install]
WantedBy=graphical.target
服务脚本代码:
#!/bin/bash
RETURN_VALUE="1"
RESET_COUNTER=0
RESET_COUNTER_TIME=0
TIME_NOW=0
echo "myapp-watchdog: myapp-watchdog started"
while [ $RETURN_VALUE != "0" ]
do
echo "myapp-watchdog: myapp started"
/opt/myapp
RETURN_VALUE=$?
TIME_NOW=$(date +"%s")
if [ $RETURN_VALUE == "0" ]
then
echo "myapp-watchdog: myapp exited with code 0"
echo "myapp-watchdog: myapp-watchdog finished"
exit 0
else
if [[ $TIME_NOW -gt $RESET_COUNTER_TIME ]]
then
RESET_COUNTER=0
fi
if [ $RESET_COUNTER == 0 ]
then
RESET_COUNTER_TIME=$TIME_NOW+60
fi
RESET_COUNTER=$((RESET_COUNTER + 1))
echo "myapp-watchdog: abnormal exit code detected. Current number of errors in the last minute: $RESET_COUNTER"
if [ $RESET_COUNTER == 5 ]
then
echo "myapp-watchdog: myapp exited with code 1"
echo "myapp-watchdog: myapp-watchdog finished"
exit 1
fi
fi
done