web-dev-qa-db-ja.com

月末に実行するcronジョブ

その月の最後の日に実行されるcronジョブを作成する必要があります。 cpanelから作成します。

どんな助けも大歓迎です。ありがとう

81
Utku Dalmaz

おそらく最も簡単な方法は、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日に実行されるため、それが問題になる場合は、別の方法を見つける必要があります。


ただし、通常は、毎月最初の日にできるだけ早くジョブを実行する方が、次のようなもので、かなり簡単で正しいです。

0 0 1 * * myjob.sh

previous月のデータを処理するようにスクリプトを変更します。

これにより、月の最後の日を把握する際に発生する可能性のある手間がなくなり、データを処理していると仮定すると、その月のすべてのデータが利用可能になります。月の最後の日の5分から真夜中に実行すると、その時から真夜中までに発生したものがすべて欠落していることがあります。

とにかく、これは通常の方法で、ほとんどの月末ジョブで行われます。


それでもreallyを月の最後の日に実行したい場合、1つのオプションは、明日が最初かどうかを(スクリプトの一部として、または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を返す可能性があるため、エラーチェックの追加を検討することもできます。上記のコードでは、単純化のためにそれを考慮していません。

152
paxdiablo

上記の方法の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
46
Indie

月の最初の日に実行されるようにcronジョブをセットアップします。次に、システムの時計を1日先に変更します。

18
Tom Anderson

ウィキペディアの後、これについてはどうですか?

55 23 L * * /full/path/to/command
10
Piohen

Paxdiabloのソリューションを適応させて、2月28日およびに実行します。 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
10
Thunder Rabbit

毎月実行するように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
7
thomson_matt
#########################################################
# 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" 
5

一部のcron実装は、月の最後の日を表す「L」フラグをサポートしています。

これらの実装のいずれかを使用して幸運であれば、それは次のように簡単です:

0 55 23 L * ?

これは、毎月最終日の午後11時55分に実行されます。

http://www.quartz-scheduler.org/documentation/quartz-1.x/tutorials/crontrigger

5
Noah Heldman

@Indieソリューションに基づくcrontabでのより安全な方法の場合(date + $()への絶対パスを使用すると、すべてのcrontabシステムで機能しません):

0 23 28-31 * * [ `/bin/date -d +1day +\%d` -eq 1 ] && myscript.sh
5
zigarn
00 23 * * * [[ $(date +'%d') -eq $(cal | awk '!/^$/{ print $NF }' | tail -1) ]] && job

Unix.comフォーラムで 関連する質問 をチェックしてください。

4
rid

AWS Cloudwatch cron実装(ラムダのスケジューリングなど)の場合、これは機能します。

55 23 L * ? *

毎月最終日の午後11時55分に実行されます。

4
Dan Herman

1つのcron行ですべての回答を接続し、dateコマンドのみを使用できます。

今日と明日になる月の日との違いを確認してください。

0 23 * * * root [ $(expr $(date +\%d -d '1 days') - $(date +\%d)  ) -le 0 ]  && echo true

これらの差が0未満の場合、月を変更し、月の最後の日があることを意味します。

3
Lukasz Stelmach

これはどうですか?

ユーザーの.bashprofile追加を編集:

export LAST_DAY_OF_MONTH=$(cal | awk '!/^$/{ print $NF }' | tail -1)

次に、このエントリをcrontabに追加します。

mm hh * * 1-7 [[ $(date +'%d') -eq $LAST_DAY_OF_MONTH ]] && /absolutepath/myscript.sh
2
Raul Baron
55 23 28-31 * * echo "[ $(date -d +1day +%d) -eq 1 ] && my.sh" | /bin/bash 
2
Donald Duck