回答:
おそらく最も簡単な方法は、3つの別々のジョブを実行することです。
55 23 30 4,6,9,11 * myjob.sh
55 23 31 1,3,5,7,8,10,12 * myjob.sh
55 23 28 2 * myjob.sh
ただし、うるう年であっても2月28日に実行されるため、問題がある場合は別の方法を見つける必要があります。
ただし、通常は、毎月1日にできるだけ早くジョブを実行する方が、次のようにかなり簡単で適切です。
0 0 1 * * myjob.sh
そして処理するために、スクリプト修正前の月のデータを。
これにより、月の最後の日を特定する際の手間が省け、データを処理していると仮定して、その月のすべてのデータを確実に利用できます。その月の最終日の5分から真夜中に実行すると、そのときから真夜中に発生することが見逃される場合があります。
とにかく、これはほとんどの月末の仕事でそれを行うための通常の方法です。
それでも本当に月の最終日に、それを実行したい、一つの選択肢は、明日は(スクリプトの一部として、またはcrontabファイル自体のいずれかで)最初のであれば、単純に検出することです。
だから、次のようなもの:
55 23 28-31 * * [[ "$(date --date=tomorrow +\%d)" == "01" ]] && myjob.sh
あなたが比較的インテリジェントなdate
プログラムを持っていると仮定すると、良いスタートになるはずです。
あなたのdate
プログラムがあなたに相対的な日付を与えるほど十分に進んでいない場合は、次のような非常に単純なプログラムを作成して、明日の日を与えることができます(の全機能は必要ありませんdate
)。
#include <stdio.h>
#include <time.h>
int main (void) {
// Get today, somewhere around midday (no DST issues).
time_t noonish = time (0);
struct tm *localtm = localtime (&noonish);
localtm->tm_hour = 12;
// Add one day (86,400 seconds).
noonish = mktime (localtm) + 86400;
localtm = localtime (&noonish);
// Output just day of month.
printf ("%d\n", localtm->tm_mday);
return 0;
}
次に、次のコマンドを使用します(tomdom
"明日の月"として呼び出した場合):
55 23 28-31 * * [[ "$(tomdom)" == "1" ]] && myjob.sh
あなたは、両方のため、エラーチェックを追加することを検討したい場合がありますがtime()
とmktime()
返すことができる-1
何かがうまくいかない場合。上記のコードは、簡単にするために、それを考慮に入れていません。
上記のものと同様に使用できる少し短い方法があります。あれは:
[ $(date -d +1day +%d) -eq 1 ] && echo "last day of month"
また、crontabエントリを更新して、28日から31日までしかチェックしないようにすることもできます。これは、月の他の日にそれを実行しても意味がないためです。それはあなたに与えるでしょう:
0 23 28-31 * * [ $(date -d +1day +%d) -eq 1 ] && myscript.sh
/bin/sh: -c: line 1: unexpected EOF while looking for matching ')'
。
[ $(date -d +1day +\%d) -eq 1 ] && run_job
cronジョブをセットアップして、月の最初の日に実行します。次に、システムのクロックを1日進めるように変更します。
ウィキペディアの後、これはどうですか?
55 23 L * * /full/path/to/command
paxdiabloのソリューションを適用して、2月28日と 29日に実行します。29日のデータが28日を上書きします。
# min hr date month dow
55 23 31 1,3,5,7,8,10,12 * /path/monthly_copy_data.sh
55 23 30 4,6,9,11 * /path/monthly_copy_data.sh
55 23 28,29 2 * /path/monthly_copy_data.sh
,29
。
55 23 28 2
思いませんか?
cronジョブを設定して、毎月実行し、次のようなシェルスクリプトを実行させることができます。このスクリプトは、明日の日数が今日の日数よりも少ないかどうか(つまり、明日が新しい月であるかどうか)を計算し、必要な処理を行います。
TODAY=`date +%d`
TOMORROW=`date +%d -d "1 day"`
# See if tomorrow's day is less than today's
if [ $TOMORROW -lt $TODAY ]; then
echo "This is the last day of the month"
# Do stuff...
fi
一部の cron実装は、月の最終日を表す「L」フラグをサポートしています。
これらの実装の1つを使用して幸運であれば、次のように簡単です。
0 55 23 L * ?
毎月最終日の午後11時55分に実行されます。
http://www.quartz-scheduler.org/documentation/quartz-1.x/tutorials/crontrigger
#########################################################
# Memory Aid
# environment HOME=$HOME SHELL=$SHELL LOGNAME=$LOGNAME PATH=$PATH
#########################################################
#
# string meaning
# ------ -------
# @reboot Run once, at startup.
# @yearly Run once a year, "0 0 1 1 *".
# @annually (same as @yearly)
# @monthly Run once a month, "0 0 1 * *".
# @weekly Run once a week, "0 0 * * 0".
# @daily Run once a day, "0 0 * * *".
# @midnight (same as @daily)
# @hourly Run once an hour, "0 * * * *".
#mm hh Mday Mon Dow CMD # minute, hour, month-day month DayofW CMD
#........................................Minute of the hour
#| .................................Hour in the day (0..23)
#| | .........................Day of month, 1..31 (mon,tue,wed)
#| | | .................Month (1.12) Jan, Feb.. Dec
#| | | | ........day of the week 0-6 7==0
#| | | | | |command to be executed
#V V V V V V
* * 28-31 * * [ `date -d +'1 day' +\%d` -eq 1 ] && echo "Tomorrow is the first today now is `date`" >> ~/message
1 0 1 * * rm -f ~/message
* * 28-31 * * [ `date -d +'1 day' +\%d` -eq 1 ] && echo "HOME=$HOME LOGNAME=$LOGNAME SHELL = $SHELL PATH=$PATH"
すべての回答を1つのcron行に接続して、 date
コマンドます。
今日と明日の日付の違いを確認してください:
0 23 * * * root [ $(expr $(date +\%d -d '1 days') - $(date +\%d) ) -le 0 ] && echo true
これらの差が0未満の場合は、月を変更し、月の最後の日があることを意味します。