毎日1時間後にcronjobを開始するにはどうすればよいですか?


16

毎日cronjobを開始する必要がありますが、毎日1時間後に開始します。私がこれまでのところ持っているものは、年の1日を除いて、ほとんどの部分で機能します:

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

年の日が365の場合、ジョブは5:00から始まりますが、翌日(うるう年を除く)は年の日が1になるため、ジョブは1:00から始まります。どうすればこの角のケースを取り除くことができますか?


1
25時間ごとに開始しない理由はありますか?
HalosGhost 14

7
そして、あなたはそれをどのくらい正確に行いますか?* / 25時間位置では解決されません。
バーチ14

@HalosGhostご提案ありがとうございます!atに基づいて簡単な実装を作成しました。
ジュリオ・ムスカレロ14

回答:


23

私が推奨する解決策は、1時間ごとにジョブを開始しますが、スクリプト自体に実行するかどうかを確認させ、25回のうち24回何もせずに終了することです。

crontab:

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

1
'%'は、crontabでバックスラッシュを使用してエスケープする必要があります。
バーチ14

@birch私はそれを知らなかった!crontabに%を含めようとしたことは一度もないと思います。修正してくれてありがとう、私は答えを編集しました。
セラダ14

1
これは私には良さそうです。私は、OPが夏時間に関して何をしたいのか見当がつきません(春が先、後が遅れる)が、OPはそれに応じて調整を行う必要があります。
エモリー

私は、部門での丸めについて少し心配しています。何らかの理由で、dateカーネルから戻っ1msた時間が、スクリプトの実行が予想される時間より前である場合、チェックは誤った結果をもたらします。
カスペルド14

1
@kasperd知りません。異なるCPUが異なる時間を報告するのは正しいかもしれません。に関してはntpd、特にこの種の問題を回避するために、クロックをジャンプするのではなく、クロックをスルーするように努力しますが、あなたは正しい、それntpdateは時々時間を後方にジャンプすることができます。cronそのスリープ遅延をmiscalculating、私はバグと考えられるであろうことはかなり確信しています!それでも3600をMOD、ポイントは取られて、この問題を回避するには、reamainderを取る前に30分にくい問題を引き起こすことがある時間を過ぎてジョブをスケジュールすること...または算術式で±1800を追加します
Celada

7

システムに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. できた

cronの単純さから逸脱する場合は、launchdを使用します。これにより、systemdの例よりも作業が少なくなります。
バーチ14

6

cronjobs以外のものを使用しても構わない場合は、あまり知られていないユーティリティをお勧めしますat。25時間以内に実行されるようにスケジュールし、プログラムを呼び出すラッパースクリプトを作成するだけです。これが最もクリーンなソリューションのようです。
たとえば、これを〜/ script.shに記述できます。

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

そして、bash ~/script.sh一度実行するだけです。

25時間に1回ジョブをスケジュールするというアイデアを提供してくれた@HalosGhostに感謝します。


2
atこの目的での使用には2つの問題があります:(1)ジョブが一度でも正しく実行できなかった場合、ジョブ自体の再スケジュールも失敗し、次の実行だけでなく、人間の通知があるまですべての将来の実行が事実上キャンセルされます。 (2)ジョブの実行にはゼロ以外の時間がかかるため、ナイーブを使用now + 25 hoursすると毎回数秒(またはそれ以上)遅れて実行されるため、このラグは時間とともに蓄積し、最終的には完全に間違って実行されます時間。
セラダ14

2
あなたは#1について正しいです。#2についてはよくわかりません。データはありませんが、クロックの変更とatジョブがトリガーされ、その後再スケジュールされるまでの遅延は、目立つほど大きくないと思います-特に、解像度がat数分に制限され、すべてのジョブを開始することを考慮してください[時間]:00。
ジュリオ・ムスカレロ14

1
@Celada:atスクリプトで次のatジョブを最初にスケジュールすると、これらの問題を回避できます。それにもかかわらず、エラーが発生した場合、チェーン全体が破損します。これは望ましい場合と望ましくない場合があります。しかし、ユースケースが「最後に失敗した場合でも常に実行される」場合at、適切なツールではありません。
ビショップ14
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.