Qu'est ce que Cron ?

culture générale informatique devops Sep 30, 2022

Hello,

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.