Qu'est ce que Cron ?
Sep 30, 2022Hello,
Tu aimerais exécuter tes scripts de façon régulière sur ton serveur
Pour ça, il y a CRON
Sauf que ce n'est pas toujours simple quand on débute
La syntaxe n'est pas intuitive
Le script fonctionne quand tu le lances à la main, mais ca déconne une fois dans Cron
Tu n'arrives pas vraiment à débugger ce qu'il se passe
C'est rageant à la fin
On voit tout de suite comment s'en sortir.
A quoi ca sert déjà ?
Qu'est ce qu'on peut vouloir bien faire de façon régulière sur son linux ?
Il y a plein de cas :
-
Faire une sauvegarder de sa BDD tous les matins et l'exporter vers un serveur
-
Envoyer un mail de rapport de l'activité de ton APP deux fois par jour
-
Exécuter un cleanup de données temporaires toutes les 5 minutes
-
Rebooter ton serveur tous les dimanches (bouuuh)
Dès qu'il y a une tâche répétitive, à faire tous les X heures ou X fois par jour/semaine/mois et surtout qu'on a pas envie d'avoir à s'en souvenir.
Parfait pour de l'automatisation.
La base
La command cron te permet de configurer tes tâches.
Chaque user a son propre "spool" : c'est à dire que tes tâches sont configurés dans ton spool sans risque d'impacter les tâches des autres utilisateurs.
Quand une tâche s'exécute, cron utilise le niveau de droit que ton user a.
Par abus de langage on dit "ta cron" pour une tâche que tu as mis dans cron
Par exemple : essayer d'accèder à /root alors que tu n'es pas root, ne fonctionnera pas dans ta cron.
Dans ton fichier .bashrc tu peux ajouter (choisit un bon éditeur, genre vim :p)
export EDITOR=nano
Ca te permettra d'avoir l'éditeur que tu prèfères pour configurer tes crons.
C'est partie :
crontab -l # pour lister tes crons
crontab -e # pour ajouter/modifier/supprimer tes crons
Cron c'est comme un agenda. Tu as 5 paramètres pour gérer les fréquences :
minute, heure, jour du mois, mois, jour de la semaine
L'ordre est important et n'est pas très intuitif.
Les 5 paramètres doivent être présents. La caractère que l'on utilise par défaut le *
Les valeurs possibles :
-
Minute : 0-59
-
Heure : 0-24
-
Jour du mois : 1-31
-
Mois : 1-12
-
Jour de la semaine : 0-6 (0 étant le dimanche)
* * * * * touch /tmp/hello
Dans cet exemple, lance la commande à chaque minute de chaque heure de chaque jour de chaque mois de chaque de la semaine !!!
Tout ça pour dire plus simple : toutes minutes.
Hé oui ! Les paramètres sont vus comme des masques ou des filtres
Tout ce qui est après le 5ème paramètre est la commande (avec les arguments) à lancer
Entrons dans les détails maintenant.
Les répétitions les plus utilisées
Exemple 1 :
30 * * * * touch /tmp/hello
Exécute la commande à la 30ème minute de chaque heure de chaque jour de chaque mois de chaque de la semaine !!!
Pour la suite, je raccourci en disant "à la 30ème de chaque heure", le reste étant sous entendu
Attention : ce n'est pas TOUTES les 30 minutes, mais une fois par heure, quand il est 30
Exemple 2 :
30 3 * * * touch /tmp/hello
Exécute la commande tous les matins à 3h30 (donc une fois par jour)
Exemple 3 :
30 3 2 * * touch /tmp/hello
Exécute la commande tous les 2ème jour du mois à 3h30 (donc une fois par mois)
Exemple 4 :
15 3 * 4 1 touch /tmp/hello
Exercice pour toi : Alors ca s'exécute quand ?
Exécute la commande tous les lundis du mois d'Avril à 3h15 du matin 🤪
Les fréquences les plus utilisés
"Ok, c'est rigolo Imrane, mais j'ai besoin de faire un truc toutes les 5 minutes ? Je fais comment ?"
C'est là qu'entre en jeu la notion d'incrément avec le slash :
Exemple 5 :
*/5 * * * * touch /tmp/hello
Exécute toutes les 5 minutes
Exemple 6 :
30 8/12 * * * touch /tmp/hello
Exécute toutes les 12 heures de temps par rapport à 8h30.
La première exécution aura lieu à soit à 20h30 soit à 8h30, en fonction de celui qui arrive en premier. Puis se répète toutes les 12 heures.
Tu peux faire la même chose pour dire tous les 3 jours ou tous les 2 mois ...
Debugger ses crons
Tu vas te rendre compte que tes crons vont dans bien des cas ne pas se lancer.
Tu codes ton script, tu le test sur ton shell, ca fonctionne. Tu passes en cron.
Et là, ca marche pas !
Premier truc à faire , c'est d'avoir des logs.
Quand cron s'exécute, tu n'es pas connecté. Cron n'a pas de console et donc tout tes prints dans ton scripts n'apparaissent pas à l'écran.
Par contre, tu peux tout "capturer" dans un fichier
command &> /tmp/myfile.txt
Là, tout ce que command écrit sur l'écran est écrit dans le fichier /tmp/myfile.txt à la place
Quand le cron est terminé, tu peux aller voir ce fichier pour être sûr qu'il contient bien ce que tu attendais.
Autre point, quand tu es dans ton shell, ton environnement est configuré pour toi : ta variable PATH contient ce dont tu as besoin, tes variables d'environnements sont mises ...
Cron ne s'exécute pas dans le shell comme toi. Il lance les commandes de façon non interactive
Imagine ton script est dans ton home directory : ~/myscript
Quand tu es dans le shell, tu vas lancer ./myscript et ca va fonctionner
Or cron ne sera pas dans ton home dir quand il va se lancer. Il faudra donc que tu mettes le chemin absolue vers ton script : /home/imrane/myscript
En plus, il ne faudra pas oublier de donner les droits d'exécution à ton fichier à ton user (chmod u+x)
Et bien entendu mettre en haut de ton script le shebang.
Parfois tu voudras lancer un truc du genre "python monfichier.py" en cron
Dans ton shell, ca marche car bash sait où aller chercher l'exécutable "python" sur ton système
Cron ne saura pas forcément le faire. Il te faudra mettre le chemin complet vers python. Par exemple, la commande suivant peut t’aider :
which python
Cette partie debug est la plus chiante au début avec cron
Quand tu ne comprends pas trop pourquoi ca marche pour toi et pas pour cron
C'est souvent, un de ces problèmes
-
chemin absolu vs chemin relatif
-
droit mal mis ou insuffisant
-
des variables présentes dans ton shell mais inconnues de cron
Tu peux aussi t'envoyer un mail quand ta cron est terminée pour être sûr que tout est ok.
Pour aller plus loin
Quelques trucs pour aller plus loin et continuer de te former.
0,5,10 * * * * command
Exécute la commande au début de chaque heure, puis à la 5eme minute de chaque heure puis à la 10ème minute de chaque heure
0 0 * * 1-5 command
Exécute la commande à minuit du Lundi au Vendredi
Si tu es à les droits suffisants, tu peux configurer les cron pour d'autres users :
crontab -u autreUser -e
Il existe des "constantes" pour planifier des crons plus facilement (elles remplacent les 5 paramètres) :
@reboot command
Exécute au restart de la machine
@yearly command
@annually command
Exécute une fois l'année, le 1 janvier à minuit
@monthly command
Exécute une fois par mois le 1 jour à minuit
@weekly command
Tu as déviné ce que ca fait
@daily command
@midnight command
Là aussi :p
@hourly command
Et aussi pour celle-là
Si tes cron peuvent se collisionner (toucher aux mêmes ressources en même temps), tu peux gérer des LOCK.
Quand ton script se lance, il vérifie s'il y a un Lock.
Si oui, il s'arrête en disant qu'il y a un script déjà en cours.
Sinon, il créé le Lock, le garde ouvert tout le long puis le détruit quand il a fini.
Il faut penser à détruire le Lock même dans les cas d'erreurs pour ne pas tout bloquer.
Comme cron exécute des commandes, tu n'es pas limité dans le choix de ton langage. J'ai des cron en PHP, en Python, en Bash, en Perl, en Ruby...
Tu as toutes les bases pour commencer à croner comme un vrai OPS :)
Voilà.
Imrane 🏖
La newsletter pour ne rien louper
Rejoins les 2500 lecteurs de la newsletter pour obtenir des conseils, des stratégies et des ressources pour développer et monétiser tes compétences Tech.