Il s'agit d'une Question canonique sur l'utilisation de cron & crontab.
Vous avez été dirigé ici parce que la communauté est assez sûre que la réponse à votre question se trouve ci-dessous. Si votre question ne reçoit pas de réponse ci-dessous, les réponses vous aideront à recueillir des informations qui aideront la communauté à vous aider. Ces informations doivent être modifiées dans votre question d'origine.
La réponse pour ' Pourquoi mon crontab ne fonctionne pas, et comment puis-je le dépanner? ' peut être vu ci-dessous. Cela concerne le système cron
avec la crontab en surbrillance.
Ceci est un wiki communautaire , si vous remarquez quelque chose de incorrect avec cette réponse ou si vous avez des informations supplémentaires, veuillez l'éditer.
Chaque utilisateur d'un système peut avoir son propre fichier crontab. L'emplacement des fichiers crontab racine et utilisateur dépend du système mais ils sont généralement inférieurs à /var/spool/cron
.
Il existe un fichier /etc/crontab
À l'échelle du système, le répertoire /etc/cron.d
Peut contenir des fragments crontab qui sont également lus et exécutés par cron. Certaines distributions Linux (par exemple, Red Hat) ont également /etc/cron.{hourly,daily,weekly,monthly}
Qui sont des répertoires, des scripts à l'intérieur desquels seront exécutés toutes les heures/jour/semaine/mois, avec le privilège root.
root peut toujours utiliser la commande crontab; les utilisateurs réguliers peuvent ou non se voir accorder l'accès. Lorsque vous modifiez le fichier crontab avec la commande crontab -e
Et l'enregistrez, crond vérifie sa validité de base mais ne garantit pas que votre fichier crontab est correctement formé. Il existe un fichier appelé cron.deny
Qui spécifiera quels utilisateurs ne peuvent pas utiliser cron. L'emplacement du fichier cron.deny
Dépend du système et peut être supprimé, ce qui permettra à tous les utilisateurs d'utiliser cron.
Si l'ordinateur n'est pas sous tension ou que le démon crond n'est pas en cours d'exécution et que la date/l'heure d'exécution d'une commande est passée, crond ne se rattrapera pas et exécutera les requêtes précédentes.
Une commande crontab est représentée par une seule ligne. Vous ne pouvez pas utiliser \
Pour étendre une commande sur plusieurs lignes. Le signe de hachage (#
) Représente un commentaire qui signifie que tout ce qui se trouve sur cette ligne est ignoré par cron. Les espaces blancs et les lignes vides sont ignorés.
Soyez TRÈS prudent lorsque vous utilisez le signe pourcentage (%
) Dans votre commande. À moins qu'ils ne soient échappés \%
, Ils sont convertis en sauts de ligne et tout après le premier %
Non échappé est passé à votre commande sur stdin.
Il existe deux formats pour les fichiers crontab:
Crontabs utilisateur
# Example of job definition:
# .---------------- minute (0 - 59)
# | .------------- hour (0 - 23)
# | | .---------- day of month (1 - 31)
# | | | .------- month (1 - 12) OR jan,feb,mar,apr ...
# | | | | .---- day of week (0 - 6) (Sunday=0 or 7)
# | | | | |
# * * * * * command to be executed
Fragments à l'échelle du système /etc/crontab
Et /etc/cron.d
# Example of job definition:
# .---------------- minute (0 - 59)
# | .------------- hour (0 - 23)
# | | .---------- day of month (1 - 31)
# | | | .------- month (1 - 12) OR jan,feb,mar,apr ...
# | | | | .---- day of week (0 - 6) (Sunday=0 or 7)
# | | | | |
# * * * * * user-name command to be executed
Notez que ce dernier nécessite un nom d'utilisateur. La commande sera exécutée en tant qu'utilisateur nommé.
Les 5 premiers champs de la ligne représentent le ou les moments où la commande doit être exécutée. Vous pouvez utiliser des nombres ou, le cas échéant, des noms de jour/mois dans la spécification d'heure.
,
) Est utilisée pour spécifier une liste, par exemple 1,4,6,8, ce qui signifie exécuter à 1,4,6,8.-
) Et peuvent être combinées avec des listes, par exemple 1-3,9-12 ce qui signifie entre 1 et 3 puis entre 9 et 12./
Peut être utilisé pour introduire une étape, par exemple 2/5 ce qui signifie commencer à 2 puis tous les 5 (2,7,12,17,22 ...). Ils ne terminent pas la fin.*
) Dans un champ signifie toute la plage de ce champ (par exemple 0-59
Pour le champ des minutes).*/2
Signifie commencer au minimum pour le champ concerné puis tous les 2 par exemple 0 pour les minutes (0,2 ... 58), 1 pour les mois (1,3 ... 11) etc.Par défaut, cron enverra toute sortie de la commande à l'utilisateur sous lequel il exécute la commande. S'il n'y a pas de sortie, il n'y aura pas de courrier. Si vous voulez que cron envoie du courrier à un autre compte, vous pouvez définir la variable d'environnement MAILTO dans le fichier crontab, par ex.
[email protected]
1 2 * * * /path/to/your/command
Vous pouvez rediriger stdout et stderr vers un fichier. La syntaxe exacte pour capturer la sortie peut varier en fonction de ce que Shell cron utilise. Voici deux exemples qui enregistrent toutes les sorties dans un fichier à /tmp/mycommand.log
:
1 2 * * * /path/to/your/command &>/tmp/mycommand.log
1 2 * * * /path/to/your/command >/tmp/mycommand.log 2>&1
Cron enregistre ses actions via syslog, qui (selon votre configuration) va souvent à /var/log/cron
Ou /var/log/syslog
.
Si nécessaire, vous pouvez filtrer les instructions cron avec par exemple.
grep CRON /var/log/syslog
Maintenant que nous avons passé en revue les bases de cron, où se trouvent les fichiers et comment les utiliser, examinons quelques problèmes courants.
Si cron n'est pas en cours d'exécution, vos commandes ne seront pas planifiées ...
ps -ef | grep cron | grep -v grep
devrait vous procurer quelque chose comme
root 1224 1 0 Nov16 ? 00:00:03 cron
ou
root 2018 1 0 Nov14 ? 00:00:06 crond
Sinon, redémarrez-le
/sbin/service cron start
ou
/sbin/service crond start
Il peut y avoir d'autres méthodes; utilisez ce que fournit votre distribution.
Les variables d'environnement disponibles sont susceptibles d'être très limitées. En règle générale, seules quelques variables sont définies, telles que $LOGNAME
, $HOME
Et $PATH
.
Il convient de noter en particulier que le PATH
est limité à /bin:/usr/bin
. La grande majorité des problèmes "mon script cron ne fonctionne pas" sont causés par ce chemin restrictif . Si votre commande se trouve dans un emplacement différent, vous pouvez résoudre ce problème de deux manières:
Fournissez le chemin d'accès complet à votre commande.
1 2 * * * /path/to/your/command
Fournissez un CHEMIN approprié dans le fichier crontab
PATH=/bin:/usr/bin:/path/to/something/else
1 2 * * * command
Si votre commande nécessite d'autres variables d'environnement, vous pouvez également les définir dans le fichier crontab.
Peu importe où le programme que vous exécutez réside sur le système de fichiers, le répertoire de travail actuel du programme lors de l'exécution de cron sera le répertoire personnel de l'utilisateur . Si vous accédez à des fichiers dans votre programme, vous devrez en tenir compte si vous utilisez des chemins d'accès relatifs, ou (de préférence) utilisez simplement des chemins d'accès qualifiés partout, et épargnez à tout le monde beaucoup de confusion.
Cron nécessite généralement que les commandes se terminent par une nouvelle ligne. Modifiez votre crontab; allez à la fin de la ligne qui contient la dernière commande et insérez une nouvelle ligne (appuyez sur Entrée).
Vous ne pouvez pas utiliser un utilisateur crontab formaté crontab pour/etc/crontab ou les fragments dans /etc/cron.d et vice versa. Un crontab formaté par l'utilisateur n'inclut pas de nom d'utilisateur à la 6ème position d'une ligne, tandis qu'un crontab formaté par le système inclut le nom d'utilisateur et exécute la commande en tant que cet utilisateur.
#!/bin/sh
En haut)Si votre date a été récemment modifiée par une mise à jour utilisateur ou système, un fuseau horaire ou autre, alors crontab commencera à se comporter de façon erratique et présentera des bogues bizarres, parfois en fonctionnement, parfois non. Il s'agit de la tentative de crontab d'essayer de "faire ce que vous voulez" lorsque le temps passe en dessous. Le champ "minute" deviendra inefficace après le changement d'heure. Dans ce scénario, seuls les astérisques seraient acceptés. Redémarrez cron et réessayez sans vous connecter à Internet (afin que la date n'ait pas la possibilité de se réinitialiser sur l'un des serveurs de temps).
Pour souligner les conseils sur les signes de pourcentage, voici un exemple de ce que cron en fait:
# cron entry
* * * * * cat >$HOME/cron.out%foo%bar%baz
va créer le fichier ~/cron.out contenant les 3 lignes
foo
bar
baz
Ceci est particulièrement intrusif lors de l'utilisation de la commande date
. Assurez-vous d'échapper aux signes de pourcentage
* * * * * /path/to/command --day "$(date "+\%Y\%m\%d")"
Debian Linux et ses dérivés (Ubuntu, Mint, etc.) ont certaines particularités qui peuvent empêcher l'exécution de vos tâches cron; en particulier, les fichiers dans /etc/cron.d
, /etc/cron.{hourly,daily,weekly,monthly}
doit :
Le dernier blesse régulièrement les utilisateurs sans méfiance; en particulier tout script dans l'un de ces dossiers nommé whatever.sh
, mycron.py
, testfile.pl
, etc. sera pas exécuté, jamais.
D'après mon expérience, ce point particulier a été de loin la raison la plus fréquente d'un cronjob non exécuté sur Debian et ses dérivés.
Voir man cron
pour plus de détails, si nécessaire.
Si vos tâches cron cessent de fonctionner, vérifiez que votre mot de passe n'a pas expiré, car une fois qu'il l'a été, toutes les tâches cron s'arrêtent.
Il y aura des messages dans /var/log/messages
similaire à celui ci-dessous qui montre des problèmes d'authentification de l'utilisateur:
(username) FAILED to authorize user with PAM (Authentication token is no longer valid; new one required)
Cron est tout bien considéré comme un planificateur très basique et la syntaxe ne permet pas facilement à un administrateur de formuler des planifications légèrement plus rares.
Considérez le travail suivant qui serait généralement expliqué à "exécuter command
toutes les 5 minutes":
*/5 * * * * /path/to/your/command
contre:
*/7 * * * * /path/to/your/command
qui ne fonctionne pas toujours exécutez command
toutes les 7 minutes .
N'oubliez pas que le / Le caractère peut être utilisé pour introduire une étape mais ces étapes ne se terminent pas au-delà de la fin d'une série, par ex. */7
qui correspond à toutes les 7 minutes des minutes 0-59
soit 0,7,14,21,28,35,42,49,56 mais entre une heure et la suivante il y aura seulement 4 minutes entre les lots , après 00:56
une nouvelle série commence à 01:00
, 01:07
etc. (et les lots ne s'exécuteront pas sur 01:03
, 01:10
, 01:17
etc.).
Créez plusieurs lots
Plutôt qu'un seul travail cron, créez plusieurs lots qui combinent le résultat dans le calendrier souhaité.
Par exemple, pour exécuter un lot toutes les 40 minutes (00:00, 00:40, 01:20, 02:00, etc.), créez deux lots, l'un qui s'exécute deux fois aux heures paires et le second qui ne fonctionne que les heures impaires:
# The following lines create a batch that runs every 40 minutes i.e.
# runs on 0:00, 0:40, 02:00, 02:40 04:00 etc to 22:40
0,40 */2 * * * /path/to/your/command
# runs on 01:20, 03:20, etc to 23:20
20 1/2 * * * /path/to/your/command
# Combined: 0:00, 0:40, 01:20, 02:00, 02:40, 03:20, 04:00 etc.
Exécutez vos lots moins fréquemment
Plutôt que d'exécuter votre lot toutes les 7 minutes, ce qui est difficile à décomposer en plusieurs lots, exécutez-le simplement toutes les 10 minutes.
Démarrez vos lots plus fréquemment (mais empêchez plusieurs lots de s'exécuter simultanément)
De nombreux horaires étranges évoluent car les temps d'exécution des lots augmentent/fluctuent, puis les lots sont planifiés avec un peu de marge de sécurité supplémentaire pour empêcher les exécutions suivantes du même lot de se chevaucher et de s'exécuter simultanément.
Au lieu de cela, pensez différemment et créez un cronjob qui échouera gracieusement lorsqu'une exécution précédente n'est pas encore terminée, mais qui s'exécutera autrement. Voir ceci Q&A :
* * * * * /usr/bin/flock -n /tmp/fcj.lockfile /usr/local/bin/frequent_cron_job
Cela démarrera presque immédiatement une nouvelle exécution une fois l'exécution précédente de/usr/local/bin/frequent_cron_job terminée.
Commencez vos lots plus fréquemment (mais quittez gracieusement lorsque les conditions ne sont pas réunies)
Étant donné que la syntaxe cron est limitée, vous pouvez décider de placer des conditions et une logique plus complexes dans le travail par lots lui-même (ou dans un script d'encapsulation autour du travail par lots existant) . Cela vous permet d'utiliser les capacités avancées de vos langages de script préférés, de commenter votre code et d'éviter les constructions difficiles à lire dans l'entrée crontab elle-même.
En bash le seven-minute-job
ressemblerait alors à quelque chose comme:
#!/bin/bash
# seven-minute-job
# This batch will only run when 420 seconds (7 min) have passed
# since the file /tmp/lastrun was either created or updated
if [ ! -f /tmp/lastrun ] ; then
touch /tmp/lastrun
fi
if [ $(( $(date +%s) - $(date -r /tmp/lastrun +%s) )) -lt 420 ] ; then
# The minimum interval of 7 minutes between successive batches hasn't passed yet.
exit 0
fi
#### Start running your actual batch job below
/path/to/your/command
#### actual batch job is done, now update the time stamp
date > /tmp/lastrun
#EOF
Que vous pouvez ensuite (essayer) exécuter en toute sécurité toutes les minutes:
* * * * * /path/to/your/seven-minute-job
Un problème différent, mais similaire, consisterait à planifier un lot pour qu'il s'exécute le premier lundi de chaque mois (ou le deuxième mercredi), etc.st ou 7e et le jour de la semaine n'est pas le lundi.
#!/bin/bash
# first-monday-of-the-month-Housekeeping-job
# exit if today is not a Monday (and prevent locale issues by using the day number)
if [ $(date +%u) != 1 ] ; then
exit 0
fi
# exit if today is not the first Monday
if [ $(date +%d) -gt 7 ] ; then
exit 0
fi
#### Start running your actual batch job below
/path/to/your/command
#EOF
Que vous pouvez ensuite (tenter) d'exécuter en toute sécurité tous les lundis:
0 0 * * 1 /path/to/your/first-monday-of-the-month-Housekeeping-job
N'utilisez pas cron
Si vos besoins sont complexes, vous pourriez envisager d'utiliser un produit plus avancé conçu pour exécuter des plannings complexes (répartis sur plusieurs serveurs) et qui prend en charge les déclencheurs, les dépendances des tâches, la gestion des erreurs, les tentatives et la surveillance des tentatives, etc. Le jargon du secteur serait "entreprise" " planification des tâches et/ou" automatisation de la charge de travail ".
Si vous avez un travail cron comme:
php /bla/bla/something.php >> /var/logs/somelog-for-stdout.log
Et en cas d'erreur, attendez-vous à ce qu'ils vous soient envoyés, mais ils ne le font pas - vérifiez cela.
PHP par défaut n'envoie pas d'erreurs à STDOUT. @see https://bugs.php.net/bug.php?id=22839
Pour résoudre ce problème, ajoutez dans le fichier php.ini de cli ou dans votre ligne (ou dans le wrapper bash de votre PHP):
Le 1er réglage vous permettra d'avoir des fatals comme 'Memory oops' et le 2e - de les rediriger tous vers STDERR. Ce n'est qu'après avoir bien dormi que tout sera envoyé au courrier de votre racine au lieu d'être simplement connecté.
Ajouter ma réponse d'ici pour être complet, et ajouter une autre ressource potentiellement utile:
cron
a un autre $PATH
que vous:Un problème fréquent que les utilisateurs font avec les entrées crontab
est qu'ils oublient que cron
s'exécute dans un environment
différent de celui qu'ils utilisent en tant qu'utilisateur connecté. Par exemple, un utilisateur crée un programme ou un script dans son $HOME
et saisissez la commande suivante pour l'exécuter:
$ ./certbot ...
La commande s'exécute parfaitement depuis sa ligne de commande. L'utilisateur ajoute ensuite cette commande à son crontab
, mais constate que cela ne fonctionne pas:
*/10 * * * * ./certbot ....
La raison de l'échec dans ce cas est que ./
est un emplacement différent pour l'utilisateur cron
que pour l'utilisateur connecté. Autrement dit, le environment
est différent! Le CHEMIN fait partie de environment
, et il est généralement différent pour l'utilisateur cron
. Pour compliquer ce problème, la environment
pour cron
n'est pas la même pour toutes les distributions * nix , et il existe plusieurs versions de cron
Une solution simple à ce problème particulier consiste à donner à l'utilisateur cron
une spécification de chemin d'accès complète dans l'entrée crontab
:
0 22 * * * /path/to/certbot .....
cron
l'utilisateur environment
?Dans certains cas, nous pouvons avoir besoin de connaître la spécification complète de environment
pour cron
sur notre système (ou nous pouvons simplement être curieux). Quel est le environment
pour l'utilisateur cron
, et en quoi est-il différent du nôtre? De plus, nous pouvons avoir besoin pour connaître le environment
pour un autre utilisateur cron
- root
par exemple ... qu'est-ce que root
l'utilisateur environment
en utilisant cron
? Une façon d'apprendre cela est de demander à cron
de nous dire:
~/
) comme suit (ou avec l'éditeur de votre choix):$ nano ~/envtst.sh
#!/bin/sh
/bin/echo "env report follows for user "$USER >> /home/you/envtst.sh.out
/usr/bin/env >> /home/you/envtst.sh.out
/bin/echo "env report for user "$USER" concluded" >> /home/you/envtst.sh.out
/bin/echo " " >> /home/you/envtst.sh.out
$ chmod a+rx ~/envtst.sh
/home/you/envtst.sh.out
. Cette sortie affichera votre environnement actuel comme $USER
vous êtes connecté en tant que:$ ./envtst.sh $$ cat /home/you/envtst.sh.out
crontab
pour le modifier:$ crontab -e -u root
crontab
:* * * * * /home/you/envtst.sh >> /home/you/envtst.sh.err 2>&1
RÉPONSE: Le fichier de sortie /home/you/envtst.sh.out
contiendra une liste des environment
pour "l'utilisateur cron root". Une fois que vous savez cela, ajustez votre entrée crontab
en conséquence.
crontab
entrée:L'entrée de programme pour crontab
est bien sûr définie dans man crontab
, et vous devriez lire ceci. Cependant, la lecture de man crontab
, et comprendre le calendrier sont deux choses différentes. Et les essais et erreurs sur une spécification d'horaire peuvent devenir très fastidieux. Heureusement, il existe une ressource qui peut aider: le gourou crontab. . Entrez vos spécifications d'horaire, et il vous expliquera l'horaire dans un langage anglais simple.
Enfin, et au risque d'être redondant avec l'une des autres réponses ici, ne vous laissez pas piéger en pensant que vous êtes limité à une seule entrée crontab
car vous avez un travail à planifier. Vous êtes libre d'utiliser autant d'entrées crontab
que nécessaire pour obtenir le planning dont vous avez besoin.