我怎样才能每天晚 1 小时开始 cronjob?

bir*_*rch 16 cron

我需要每天开始一个 cronjob,但每天晚一个小时。到目前为止,我所做的大部分工作,除了一年中的 1 天:

0 0 * * * sleep $((3600 * (10#$(date +\%j) \% 24))) && /usr/local/bin/myprog
Run Code Online (Sandbox Code Playgroud)

当一年中的第 365 天时,作业将从 5:00 开始,但第二天(不包括闰年)将一年中的某一天设为 1,因此作业将从 1:00 开始。我怎样才能摆脱这个角落案例?

Cel*_*ada 23

我的首选解决方案是每小时启动一次作业,但让脚本本身检查是否该运行并退出,25 次中有 24 次不做任何事情。

定时任务:

0 * * * *    /usr/local/bin/myprog
Run Code Online (Sandbox Code Playgroud)

在顶部myprog

[ 0 -eq $(( $(date +%s) / 3600 % 25 )) ] || exit 0
Run Code Online (Sandbox Code Playgroud)

如果您不想对脚本本身进行任何更改,您也可以将“运行时间”检查放在 crontab 条目中,但它会产生很长的难看的一行:

0 * * * *    [ 0 -eq $(( $(date +\%s) / 3600 \% 25 )) ] && /usr/local/bin/myprog
Run Code Online (Sandbox Code Playgroud)


Bra*_*iam 7

如果您的系统有 systemd,您可以为此使用计时器事件。只需定义一个新的 service,它应该包含您要执行的命令/任务,然后使用以下OnUnitActiveSec选项创建一个计时器事件:

[Unit]
Description=daily + 1 hour task

[Timer]
OnUnitActiveSec=25h # run 25 hours after service was last started
AccuracySec=10min

[Install]
WantedBy=timers.target
Run Code Online (Sandbox Code Playgroud)

对文件使用相同的名称,除了.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
    
    Run Code Online (Sandbox Code Playgroud)
  5. 使用验证计时器 systemctl list-timers
  6. 完毕。


Giu*_*llo 6

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

echo "bash ~/script.sh" | at now + 25 hours
/usr/bin/yourprogram
Run Code Online (Sandbox Code Playgroud)

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

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

  • 为此目的使用`at`有两个问题:(1)如果作业即使一次也未能正确执行,它也可能无法重新安排自己,然后不仅是下一次执行,而且所有未来的执行都被有效地取消,直到有人通知,以及 (2) 由于作业需要一些非零时间来运行,使用简单的“现在 + 25 小时”意味着它每次将运行几秒钟(或更长时间),并且这种滞后会随着时间的推移而增加,使其最终在完全错误的时间运行。 (2认同)
  • 你对#1 是正确的;我不太确定#2。虽然我没有任何数据,但我认为时钟更改和 at 作业被触发并随后重新安排之间的延迟并没有大到足以引起注意——特别是考虑到 `at` 的分辨率仅限于分钟和在 [time]:00 开始所有作业。 (2认同)