我已尝试此解决方案来防止重复的 cronjob 运行。
30,31 12 * * * /usr/bin/flock -n /tmp/my.lockfile ~/Desktop/test.sh >> ~/Desktop/test.log 2>&1
并且脚本test.sh
有
#!/bin/bash
for i in {1..40};do
echo "hello$i"
sleep 2
done
脚本test.sh
已成功阻止在 12:31 运行,但它已停止,我想恢复它。我怎样才能让它只暂停,不停止并恢复?可能吗?
答案1
您可以添加测试在脚本的开头,检查是否有其他早期启动的脚本实例,如果是,则当前实例将进入休眠状态。如下所示:
while ps aux | grep -v 'grep' | grep "$0" | sed -e "/$$/p" -e "/$$/,$ d" | grep -vq "$$"
do sleep 1
done
在哪里:
变量
$0
包含脚本名称(和执行路径);该变量
$$
包含脚本当前运行实例的 PID;ps aux
- 输出当前流程;grep -v 'grep'
grep
- 保留前一个命令输出中包含的行;grep "$0"
- 仅输出与当前脚本名称相关的行;sed -e "/$$/p" -e "/$$/,$ d"
- 删除脚本的较新实例;删除包含当前实例 PID 的行之后的所有行;grep -vq "$$"
- 这是实际的测试-q
,当删除当前实例的 PID 行时,将返回0
(true - 至少有一个较旧的脚本实例)或1
(false - 显然这是最新的现有脚本实例)-v
。
这是一个完整的例子:
#!/bin/bash
while ps aux | grep -v 'grep' | grep "$0" | sed -e "/$$/p" -e "/$$/,$ d" | grep -vq "$$"
do
sleep 1
echo -n '.'
done
date +"%T"
for i in {1..5};do
echo "hello$i"
sleep 2
done
以下是我所做的测试:
此外,您还可以创建一个启动器脚本,它将以上述方式执行您的实际脚本。
$ cat ~/Desktop/test-cron-launcher.sh
#!/bin/bash
LAUNCH_TIME="$(date +"%T")"
while ps aux | grep -v 'grep' | grep "$0" | sed -e "/$$/p" -e "/$$/,$ d" | grep -vq "$$"
do sleep 1
done
echo "Job from $LAUNCH_TIME begin at $(date +"%T")"
. "$HOME/Desktop/test.sh"
$ cat ~/Desktop/test.sh
#!/bin/bash
for i in {1..40};do
echo "hello$i"
sleep 2
done
$ crontab -l | grep 'test'
30,31 12 * * * "$HOME/Desktop/test-cron-launcher.sh" >> "$HOME/Desktop/test.log" 2>&1
另请阅读: