我有一个简单的脚本,用于检查某些长时间运行的进程(即永远)是否正在运行,如果没有,则重新启动它们(省略了一些细节):
#!/bin/bash
PROC_LIST=$(ps ax | grep <stuff>)
while read cfg
do
PROC_NAME=$(echo $cam_cfg | cut -f2 -d' ')
PROC_COUNT=$(echo $PROC_LIST | tr ' ' '\n' | grep $PROC_NAME | wc -l)
if [[ $PROC_COUNT -eq 0 ]]; then
echo "Starting process for $PROC_NAME"
<process start> 2> /dev/null &
fi
done < $CONFIG
这里的想法是获取相关进程的列表,并查看它们是否包含配置文件中指定的关键字。我怀疑重要的一点是,如果需要的话,我会使用 & 来分叉该进程。如果我手动运行该脚本,它就会起作用。
我希望 Systemd 每 30 秒运行一次这个脚本。为此,我创建了以下单元:
服务:
[Unit]
Description=Check processes
[Service]
Type=oneshot
WorkingDirectory=/home/user/scripts
ExecStart=/home/user/scripts/watchdog.sh /config
User=user
[Install]
WantedBy=multi-user.target
定时器:
[Unit]
Description=Check running processes
[Timer]
OnBootSec=30s
OnActiveSec=30s
[Install]
WantedBy=timers.target
当使用 Type=oneshot 时,我发现监视的进程根本没有启动,因此计时器每隔 30 秒就会启动并尝试再次启动所有进程。我怀疑这是因为我正在分叉,因此当服务结束时,所有子进程也会结束。
当我使用 Type=forking 时,我看到进程启动并按要求保持。然而,在这种情况下,计时器永远不会被调度,因此永远不会再次运行。我怀疑这是因为它没有意识到分叉服务需要重新激活。所以:
- 如何解决上述问题,以便无论发生什么情况,脚本每 30 秒运行一次?
- 这个练习让我觉得我实际上是在对抗 systemd。有没有更好的设计呢? CONFIG 是一个任意且可能是动态的列表,因此我有点不愿意为每个条目创建一个 systemd 服务。