Travail Cron à exécuter le dernier jour du mois

J'ai besoin de créer un travail cron qui s'exécutera tous les derniers jours du mois. Je vais le créer à partir de cpanel.

Toute aide est appréciée. Merci

66
demandé sur Bernd Elkemann 2011-05-26 17:22:55

14 réponses

Peut-être le moyen le plus simple est de simplement faire trois tâches distinctes:

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

Cela se déroulera le 28 février, même les années bissextiles, donc si c'est un problème, vous devrez trouver un autre moyen.


Cependant, il est généralement à la fois beaucoup plus facile et correct d'exécuter le travail le plus tôt possible le premier jour de chaque mois, avec quelque chose comme:

0 0 1 * * myjob.sh

Et modifiez le script pour traiter le mois précédent données.

Cela supprime tous les tracas que vous pourriez rencontrer pour déterminer quel jour est le dernier du mois, et garantit également que toutes les données pour ce mois sont disponibles, en supposant que vous traitez des données. Courir à cinq minutes à minuit le dernier jour du mois peut vous voir manquer tout ce qui se passe entre alors et minuit.

C'est la façon habituelle de le faire de toute façon, pour la plupart des emplois de fin de mois.


Si vous voulez toujours vraiment l'exécuter sur le dernier jour du mois, une option consiste simplement à détecter si demain est le premier (soit dans le cadre de votre script, soit dans le crontab lui-même).

Donc, quelque chose comme:

55 23 28-31 * * [[ "$(date --date=tomorrow +\%d)" == "01" ]] && myjob.sh

Devrait être un bon début, en supposant que vous avez un programme date relativement intelligent.

Si votre programme date n'est pas assez avancé pour vous donner des dates relatives, vous pouvez simplement créer un programme très simple pour vous donner le jour du mois de demain (vous n'avez pas besoin de la puissancefull de date), tels que:

#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;
}

Et puis utilisez (en supposant que vous l'avez appelé tomdom pour "le jour du mois de demain"):

55 23 28-31 * * [[ "$(tomdom)" == "1" ]] && myjob.sh

Bien que vous souhaitiez peut-être envisager d'ajouter une vérification d'erreur puisque time() et mktime() peuvent renvoyer -1 si quelque chose ne va pas. Le code ci-dessus, pour des raisons de simplicité, ne tient pas compte de cela.

130
répondu paxdiablo 2015-06-02 08:12:04

Il y a une méthode légèrement plus courte qui peut être utilisée similaire à l'une de celles ci-dessus. C'est:

[ $(date -d +1day +%d) -eq 1 ] && echo "last day of month"

En outre, l'entrée crontab pourrait être mise à jour pour ne vérifier que le 28 au 31 car il est inutile de l'exécuter les autres jours du mois. Ce qui vous donnerait:

0 23 28-31 * * [ $(date -d +1day +%d) -eq 1 ] && myscript.sh
40
répondu Indie 2011-08-26 11:41:17

Configurez un travail cron à exécuter le premier jour du mois. Ensuite, changez l'horloge du système pour avoir un jour d'avance.

16
répondu Tom Anderson 2011-05-26 13:43:08

Adapter la solution de paxdiablo, Je cours le 28 et le 29 février. Les données du 29 écrasent le 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
répondu Thunder Rabbit 2013-05-17 07:40:20

Qu'en est-il de celui-ci, après Wikipedia?

55 23 L * * /full/path/to/command
9
répondu Piohen 2012-03-15 11:17:35

Vous pouvez configurer un travail cron pour l'exécuter tous les jours du mois, et le faire exécuter un script shell comme le suivant. Ce script détermine si le nombre de jours de demain est inférieur à celui d'aujourd'hui (c'est-à-dire si demain est un nouveau mois), puis fait ce que vous voulez.

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
6
répondu thomson_matt 2011-05-26 13:25:49
00 23 * * * [[ $(date +'%d') -eq $(cal | awk '!/^$/{ print $NF }' | tail -1) ]] && job

Consultez une question connexe sur le unix.com forum.

4
répondu rid 2011-05-26 13:26:21

Pour une méthode plus sûre dans une crontab basée sur une solution @ Indie (utilisez le chemin absolu pour date + $() ne fonctionne pas sur tous les systèmes crontab):

0 23 28-31 * * [ `/bin/date -d +1day +\%d` -eq 1 ] && myscript.sh
4
répondu zigarn 2013-02-28 13:52:29

certaines implémentations cron prennent en charge l'indicateur "L" pour représenter le dernier jour du mois.

Si vous avez de la chance d'utiliser l'une de ces implémentations, c'est aussi simple que:

0 55 23 L * ?

Qui se déroulera à 23h55 le dernier jour de chaque mois.

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

4
répondu Noah Heldman 2013-09-05 01:27:36

Vous pouvez simplement connecter toutes les réponses dans une ligne cron et utiliser uniquement la commande date.

Il suffit de vérifier la différence entre le jour du mois qui est aujourd'hui et sera demain:

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

Si cette différence est inférieure à 0, cela signifie que nous changeons le mois et qu'il y a le dernier jour du mois.

3
répondu Lukasz Stelmach 2014-01-10 12:07:14
#########################################################
# 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" 
3
répondu Leslie Satenstein 2015-02-28 17:53:41

Et ça?

Modifier .bashprofile ajout de l'utilisateur:

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

Puis ajoutez cette entrée à crontab:

mm hh * * 1-7 [[ $(date +'%d') -eq $LAST_DAY_OF_MONTH ]] && /absolutepath/myscript.sh
1
répondu Raul Baron 2014-06-18 01:37:49
55 23 28-31 * * echo "[ $(date -d +1day +%d) -eq 1 ] && my.sh" | /bin/bash 
1
répondu Donald Duck 2018-09-12 03:26:42

Pour L'implémentation AWS Cloudwatch cron (planification de Lambdas, etc..) cela fonctionne:

55 23 L * ? *

Courir à 23h55 le dernier jour de chaque mois.

-1
répondu Dan Herman 2018-03-29 18:01:46