我需要每天启动一个定时任务,但每天晚一个小时。到目前为止,我所拥有的大部分内容都有效,除了一年中的一天:
0 0 * * * sleep $((3600 * (10#$(date +\%j) \% 24))) && /usr/local/bin/myprog
当一年中的某一天为 365 时,作业将从 5:00 开始,但第二天(不包括闰年)将有一年中的某一天为 1,因此作业将从 1:00 开始。我怎样才能摆脱这个极端情况?
答案1
我首选的解决方案是每小时启动一次作业,但让脚本本身检查是否到了运行时间,然后在 25 次中有 24 次不执行任何操作的情况下退出。
定时任务:
0 * * * * /usr/local/bin/myprog
在顶端myprog
:
[ 0 -eq $(( $(date +%s) / 3600 % 25 )) ] || exit 0
如果您不想对脚本本身进行任何更改,您也可以将“运行时间”检查放入 crontab 条目中,但这会导致很长的难看的行:
0 * * * * [ 0 -eq $(( $(date +\%s) / 3600 \% 25 )) ] && /usr/local/bin/myprog
答案2
如果您的系统有 systemd,您可以为此使用计时器事件。只需定义一个新服务,其中应包含要执行的命令/任务,然后使用以下OnUnitActiveSec
选项创建计时器事件:
[Unit]
Description=daily + 1 hour task
[Timer]
OnUnitActiveSec=25h # run 25 hours after service was last started
AccuracySec=10min
[Install]
WantedBy=timers.target
对文件使用相同的名称,只不过.service
使用.timer
.
合成:
job.service
在目录中创建一个名为/etc/systemd/system/
.- 填写必要的信息。您可以使用 来验证配置
systemctl status job.service
。 job.timer
创建一个名为的文件/etc/systemd/system/
。填写所需信息:
[Unit] Description=daily + 1 hour task [Timer] OnUnitActiveSec=25h # run 25 hours after service was last started AccuracySec=10min [Install] WantedBy=timers.target
- 使用验证计时器
systemctl list-timers
- 完毕。
答案3
如果您不介意使用 cronjobs 以外的其他工具,我建议您使用鲜为人知的实用程序at
。只需编写一个包装器脚本,将其安排在 25 小时内运行,然后调用您的程序。这似乎是最干净的解决方案。
例如,您可以在 ~/script.sh 中编写以下内容:
echo "bash ~/script.sh" | at now + 25 hours
/usr/bin/yourprogram
然后只需运行bash ~/script.sh
一次即可。
感谢 @HalosGhost 提出每 25 小时安排一次工作的想法。