cronjobで45日ごとにシェルスクリプトを実行するには?
答え1
正確に45日は必要ありませんが、「1ヶ月半」で十分であれば、簡単なアプローチは3ヶ月ごとに開始し、毎月来月中旬に1回実行することです。 。それら:
0 12 1 1,4,7,10 * /path/to/script
0 12 16 2,5,8,11 * /path/to/script
他の答えは通常、ランダムな間隔については明らかに良いですが、とにかく45日は月の長さに基づいているように聞こえます。人間のユーザーは、毎日1日か2日ずつ正確な日付ドリフトを確認するよりも、月の初めまたは中旬に何が起こるのかをよく知ることができます。
答え2
cronはこの要件への簡単で簡単な変換をサポートしていないので、タイムスタンプファイルと毎日のcronジョブを使用してこれを処理します。
0 0 * * * /path/to/wrapper/script/below.sh
ラッパースクリプト:
#!/bin/bash
timestampfile=/var/run/this-job/timetampfile
# exit now if it hasn't been 45 days
((
$(date +%s) - $(stat -c %Z "$timestampfile")
<
(45 * 24 * 60 * 60)
)) && exit 0
touch "$timestampfile"
: run real script here
これはいくつかのリスクを引き起こします。
- 誰かがタイムスタンプファイルを削除しました。
- 誰かがタイムスタンプファイルをタッチしました(いいか悪い)
- 実際のスクリプトが45日ごとに実行されることはcron作業項目では明確ではありません。
答え3
に基づいてスタックオーバーフローに対するこの回答、次の構文を使用してこれを行うことができます。
00 12 * * * test $(( $(date +\%s)/24/60/60\%45 )) = 20 && your_script
このタスクは毎日正午に実行されます。次に、新起源以降の日数のモジュラスを計算し、指定したモジュラスと等しいかどうかをテストします。この例では20を指定しましたが、これは今日(2018-05-09 00:00 GMTから23:59 GMTの間)、今日から45日などでtrueと評価されます。以下を使用して、以下を計算/テストできます。
$ echo $(( $(date +%s)/24/60/60%45 ))
20
$ echo $(( $(date -d '+45 days' +%s)/24/60/60%45 ))
20
$ echo $(( $(date -d '+44 days' +%s)/24/60/60%45 ))
19
(UTCタイムゾーンを超えている場合は、時間を考慮する必要があります。)
答え4
crl
使用するために公開しようとしたときに同様の問題が発生しましたOpenBSD 6.6
。次のスクリプトを使用して、次回の起動時に最初にスケジュールします。
#!/bin/sh
# copy current crontab to file without launching script
/usr/bin/crontab -l | grep -v "/var/publishCRL.sh" > /var/tmpCron
# add entry for 45 days from now
# 45 days = 3888000 seconds
/bin/echo $(date -j -r `expr $(date +%s) + 3888000` "+%M %H %d %m")" * /var/publishCRL.sh" >> /var/tmpCron
# load edited crontab
/usr/bin/crontab /var/tmpCron
# cleanup
/bin/rm /var/tmpCron
# do CRL stuff