如何每天晚 1 小时启动 cronjob?

如何每天晚 1 小时启动 cronjob?

我需要每天启动一个定时任务,但每天晚一个小时。到目前为止,我所拥有的大部分内容都有效,除了一年中的一天:

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.

合成:

  1. job.service在目录中创建一个名为/etc/systemd/system/.
  2. 填写必要的信息。您可以使用 来验证配置systemctl status job.service
  3. job.timer创建一个名为的文件/etc/systemd/system/
  4. 填写所需信息:

    [Unit]
    Description=daily + 1 hour task
    
    [Timer]
    OnUnitActiveSec=25h # run 25 hours after service was last started
    AccuracySec=10min
    
    [Install]
    WantedBy=timers.target
    
  5. 使用验证计时器systemctl list-timers
  6. 完毕。

答案3

如果您不介意使用 cronjobs 以外的其他工具,我建议您使用鲜为人知的实用程序at。只需编写一个包装器脚本,将其安排在 25 小时内运行,然后调用您的程序。这似乎是最干净的解决方案。
例如,您可以在 ~/script.sh 中编写以下内容:

echo "bash ~/script.sh" | at now + 25 hours
/usr/bin/yourprogram

然后只需运行bash ~/script.sh一次即可。

感谢 @HalosGhost 提出每 25 小时安排一次工作的想法。

相关内容