我需要每天开始一个 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)
如果您的系统有 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
.
合成:
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
Run Code Online (Sandbox Code Playgroud)systemctl list-timers
如果您不介意使用 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 小时安排一次作业的想法。