Ce que vous saurez faire
Ce tutoriel vous apprend a utiliser cron, le planificateur de taches Unix/Linux, pour automatiser les operations recurrentes de votre PME senegalaise. Que vous deviez sauvegarder votre base de donnees chaque nuit a 2h, envoyer un rapport de ventes chaque lundi matin a l’equipe, renouveler vos certificats SSL tous les 60 jours, nettoyer les fichiers temporaires, ou synchroniser votre stock vers le cloud toutes les heures, cron est l’outil incontournable. Vous apprendrez la syntaxe crontab exacte (avec ses pieges), comment editer votre crontab utilisateur et celui du systeme, les bonnes pratiques pour les variables d’environnement, les redirections de sortie indispensables, et comment deboguer un cron qui ne se declenche pas. A la fin, vous saurez aussi quand preferer systemd timers qui offrent des fonctionnalites avancees comme les dependances et le catch-up.
Etape 1 : Verifier que cron est actif
Cron est generalement installe par defaut. Verifiez que le service tourne avant de planifier.
# Statut du service cron sudo systemctl status cron # Ubuntu/Debian : cron # CentOS/Rocky : crond sudo systemctl status crond # Si CentOS # Activer au demarrage sudo systemctl enable cron sudo systemctl start cron # Verifier l'installation which crontab # /usr/bin/crontab # Aide man crontab man 5 crontab # Documentation de la syntaxe
Etape 2 : Comprendre la syntaxe crontab
Une ligne crontab comporte 5 champs temporels suivis de la commande. Retenez l’ordre : minute, heure, jour du mois, mois, jour de la semaine.
# Structure generale # * * * * * commande # | | | | | # | | | | +---- jour de la semaine (0-6, 0=dimanche, ou mon,tue,wed...) # | | | +------- mois (1-12, ou jan,feb,mar...) # | | +---------- jour du mois (1-31) # | +------------- heure (0-23) # +---------------- minute (0-59) # Exemples concrets : # Chaque minute * * * * * /usr/local/bin/check.sh # Tous les jours a 2h30 30 2 * * * /usr/local/bin/backup.sh # Tous les lundis a 9h00 0 9 * * 1 /usr/local/bin/rapport_semaine.sh # Le 1er de chaque mois a 0h 0 0 1 * * /usr/local/bin/rapport_mois.sh
Etape 3 : Operateurs speciaux
Les operateurs *, ,, -, et / permettent d’exprimer des planifications precises sans enumerer chaque valeur.
# Toutes les 15 minutes */15 * * * * /usr/local/bin/heartbeat.sh # Toutes les 5 minutes de 8h a 18h du lundi au vendredi */5 8-18 * * 1-5 /usr/local/bin/business_hours.sh # A 0h00 et 12h00 0 0,12 * * * /usr/local/bin/two_per_day.sh # A 8h, 13h et 18h 0 8,13,18 * * * /usr/local/bin/three_per_day.sh # Toutes les 2 heures 0 */2 * * * /usr/local/bin/every_two_hours.sh # Les weekends (samedi et dimanche) 0 10 * * 6,0 /usr/local/bin/weekend.sh # ou 0 10 * * sat,sun /usr/local/bin/weekend.sh
Etape 4 : Raccourcis predefinis
Pour les cas courants, cron accepte des raccourcis plus lisibles que la syntaxe numerique.
@reboot /usr/local/bin/init_au_boot.sh @yearly /usr/local/bin/annuel.sh # equivaut a 0 0 1 1 * @annually /usr/local/bin/annuel.sh # meme chose @monthly /usr/local/bin/mensuel.sh # 0 0 1 * * @weekly /usr/local/bin/hebdo.sh # 0 0 * * 0 @daily /usr/local/bin/quotidien.sh # 0 0 * * * @midnight /usr/local/bin/minuit.sh # meme que @daily @hourly /usr/local/bin/horaire.sh # 0 * * * * # Exemple concret @reboot /usr/local/bin/monter_sauvegardes.sh @daily /usr/local/bin/backup_mysql.sh @weekly /usr/local/bin/nettoyage_cache.sh
Etape 5 : Editer son crontab utilisateur
Chaque utilisateur a son propre crontab. Editez-le avec crontab -e. Ne jamais editer directement les fichiers dans /var/spool/cron.
# Editer MON crontab crontab -e # Au premier lancement, choisir l'editeur (nano recommande pour debutants) # Puis ajouter les taches # Lister MON crontab crontab -l # Supprimer MON crontab (attention, pas de confirmation) crontab -r # Editer le crontab d'un autre utilisateur (besoin de sudo) sudo crontab -u deploy -e sudo crontab -u deploy -l # Sauvegarde avant modification crontab -l > ~/crontab_backup_$(date +%F).txt # Restaurer depuis fichier crontab ~/crontab_backup_2026-04-23.txt
Etape 6 : Ecrire une premiere tache simple
Commencez par une tache qui s’execute chaque minute et ecrit dans un fichier. Cela permet de verifier que cron fonctionne dans votre environnement avant d’ajouter des operations complexes.
crontab -e
# Test minimal : ecrire la date chaque minute * * * * * date >> /tmp/cron_test.log 2>&1
# Attendre 2-3 minutes puis verifier cat /tmp/cron_test.log # Thu Apr 23 14:30:01 GMT 2026 # Thu Apr 23 14:31:01 GMT 2026 # Thu Apr 23 14:32:01 GMT 2026 # Supprimer la ligne de test une fois la validation faite crontab -e
Etape 7 : Rediriger la sortie correctement
Par defaut, cron envoie la sortie standard et les erreurs par email a l’utilisateur. Sans serveur mail, ces emails s’accumulent. Redirigez toujours vos sorties.
# Mauvais : sortie perdue ou en spam 30 2 * * * /usr/local/bin/backup.sh # Bon : logs dans un fichier 30 2 * * * /usr/local/bin/backup.sh >> /var/log/backup.log 2>&1 # Silencer completement (attention : invisible si erreur) 30 2 * * * /usr/local/bin/backup.sh > /dev/null 2>&1 # Capturer uniquement les erreurs 30 2 * * * /usr/local/bin/backup.sh > /dev/null 2>> /var/log/backup_errors.log # Explications : # >> fichier : ajoute la sortie standard # 2>&1 : redirige les erreurs vers la sortie standard (meme fichier) # 2>> fichier : ajoute UNIQUEMENT les erreurs
Etape 8 : Gerer les variables d’environnement
Cron execute les commandes dans un environnement minimal : PATH reduit, pas de $HOME, etc. C’est la cause #1 des scripts qui marchent en ligne de commande mais pas en cron.
# En haut du crontab, definir les variables SHELL=/bin/bash PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin HOME=/home/admin MAILTO=admin@pme-dakar.sn # Email pour recevoir les rapports # Tache qui utilise ces variables 0 3 * * * /home/admin/scripts/backup.sh >> /var/log/backup.log 2>&1 # Alternative : tout definir dans le script lui-meme # Au debut du script : #!/bin/bash export PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin export HOME=/home/admin cd /var/www/mon_app source /home/admin/.env
Etape 9 : Cron systeme dans /etc/cron.d/
En plus des crontabs utilisateur, le systeme a des fichiers dans /etc/cron.d/, /etc/cron.daily/, /etc/cron.hourly/, /etc/cron.weekly/, /etc/cron.monthly/. Pratique pour les taches deployees par paquets.
# Creer une tache systeme sudo nano /etc/cron.d/backup-mysql # Syntaxe legerement differente : un champ USER avant la commande # min hour dom mon dow user commande 30 2 * * * admin /usr/local/bin/backup_mysql.sh >> /var/log/backup.log 2>&1 # Permissions importantes sudo chmod 644 /etc/cron.d/backup-mysql sudo chown root:root /etc/cron.d/backup-mysql # Scripts executables dans les dossiers periodiques sudo cp nettoyage.sh /etc/cron.daily/ sudo chmod +x /etc/cron.daily/nettoyage.sh # Attention : les noms ne doivent pas contenir de point ni d'extension # Tester run-parts sudo run-parts --test /etc/cron.daily/
Etape 10 : Cas concret – sauvegarde complete
Mettons en place une vraie sauvegarde nocturne : base MySQL + fichiers web + rotation sur 14 jours + notification email.
sudo nano /usr/local/bin/backup_complet.sh
#!/bin/bash
set -euo pipefail
DATE=$(date +%Y%m%d_%H%M%S)
BACKUP_DIR="/backups"
RETENTION=14
LOG="/var/log/backup_complet.log"
exec >> "$LOG" 2>&1
echo "=== Debut sauvegarde $DATE ==="
# MySQL
mysqldump -u backup -p'PASS' --all-databases | gzip > "$BACKUP_DIR/mysql_${DATE}.sql.gz"
# Fichiers web
tar -czf "$BACKUP_DIR/www_${DATE}.tar.gz" /var/www/html
# Configs
tar -czf "$BACKUP_DIR/etc_${DATE}.tar.gz" /etc/nginx /etc/mysql
# Rotation
find "$BACKUP_DIR" -name "*.gz" -mtime +$RETENTION -delete
# Notification
TAILLE=$(du -sh "$BACKUP_DIR" | cut -f1)
echo "Sauvegarde OK. Taille totale : $TAILLE"
echo "=== Fin sauvegarde ==="
sudo chmod +x /usr/local/bin/backup_complet.sh # Test manuel d'abord sudo /usr/local/bin/backup_complet.sh # Si OK, programmer sudo crontab -e # Tous les jours a 2h30 30 2 * * * /usr/local/bin/backup_complet.sh
Etape 11 : Deboguer un cron qui ne fonctionne pas
90% des bugs de cron viennent de l’environnement. Voici la methodologie de debug.
# 1. Verifier que cron est actif sudo systemctl status cron # 2. Consulter les logs de cron grep CRON /var/log/syslog | tail -20 # ou sur certaines distrib sudo tail -f /var/log/cron # 3. Verifier que la tache est bien enregistree crontab -l # 4. Tester la commande en tant qu'utilisateur avec env minimal env -i /bin/bash -c "/usr/local/bin/monscript.sh" # 5. Ajouter du logging detaille dans le script set -x exec > /tmp/debug.log 2>&1 # 6. Simuler l'environnement cron * * * * * env > /tmp/cron_env.txt # Comparer avec votre env interactif : env > /tmp/shell_env.txt diff /tmp/cron_env.txt /tmp/shell_env.txt # 7. Verifier les permissions ls -l /usr/local/bin/monscript.sh # Doit etre executable
Etape 12 : Exclusion concurrente avec flock
Si une tache met plus de temps que prevu, elle peut etre lancee une deuxieme fois en parallele. flock pose un verrou qui empeche l’execution concurrente.
# Sans flock : deux instances possibles si le script prend >1 min * * * * * /usr/local/bin/check_every_minute.sh # Avec flock : une seule instance * * * * * flock -n /tmp/check.lock /usr/local/bin/check_every_minute.sh # Options flock # -n : ne pas attendre, echouer immediatement si verrou pris # -w 10 : attendre 10 secondes max pour le verrou # -x : verrou exclusif (defaut) # Exemple reel : sync toutes les 5 minutes mais sans recouvrement */5 * * * * flock -n /tmp/sync.lock /usr/local/bin/sync_stock.sh >> /var/log/sync.log 2>&1 # Verifier qu'un verrou est bien liberé apres execution lsof /tmp/sync.lock
Etape 13 : Alternative moderne – systemd timers
Sur les systemes modernes, systemd timers offrent des avantages : logs integres via journalctl, dependances entre services, et catch-up (execution si le serveur etait eteint).
# Creer le service sudo nano /etc/systemd/system/backup.service
[Unit] Description=Sauvegarde MySQL quotidienne After=network.target mysql.service [Service] Type=oneshot ExecStart=/usr/local/bin/backup_mysql.sh User=admin Group=admin
sudo nano /etc/systemd/system/backup.timer
[Unit] Description=Declenche la sauvegarde chaque jour a 2h30 [Timer] OnCalendar=*-*-* 02:30:00 Persistent=true RandomizedDelaySec=300 [Install] WantedBy=timers.target
# Activer et demarrer sudo systemctl daemon-reload sudo systemctl enable backup.timer sudo systemctl start backup.timer # Verifier sudo systemctl list-timers # Voir la prochaine execution # Logs sudo journalctl -u backup.service -f # Declencher manuellement sudo systemctl start backup.service # Desactiver sudo systemctl disable backup.timer
Etape 14 : Bonnes pratiques production
Quelques regles pour que vos crons restent fiables dans la duree.
# 1. Toujours chemins absolus # Mauvais 0 2 * * * cd /var/www && ./backup.sh # Bon 0 2 * * * /usr/local/bin/backup_www.sh # 2. Script qui change de dossier en interne #!/bin/bash cd /var/www || exit 1 tar -czf /backups/www.tar.gz . # 3. Tester l'execution en cron manuellement at now + 1 minute -f /usr/local/bin/backup.sh # 4. Documenter le crontab # Ajouter des commentaires expliquant chaque ligne # =================================== # BACKUPS # =================================== 30 2 * * * /usr/local/bin/backup_mysql.sh 30 3 * * * /usr/local/bin/backup_www.sh 0 4 * * 0 /usr/local/bin/backup_hebdo.sh # =================================== # MAINTENANCE # =================================== 0 5 * * * /usr/local/bin/rotate_logs.sh */10 * * * * /usr/local/bin/monitor.sh # 5. Monitoring des crons : envoyer un ping vers une URL externe # Services comme healthchecks.io ou cronitor.io 0 2 * * * /usr/local/bin/backup.sh && curl -fsS https://hc-ping.com/UUID
Erreurs
Chemins relatifs dans les commandes : cron ne s’execute pas dans votre repertoire courant. Utilisez toujours des chemins absolus ou un cd explicite en debut de script.
PATH incomplet : cron demarre avec un PATH minimal. Des commandes comme mysqldump ou aws peuvent etre introuvables. Definissez PATH en haut du crontab ou utilisez les chemins complets /usr/bin/mysqldump.
Oublier la redirection des erreurs : sans 2>&1, vous ne verrez pas pourquoi une tache echoue. Redirigez systematiquement la sortie ET les erreurs vers un fichier log.
Executer plusieurs instances simultanees : un script de sync qui met 10 minutes planifie toutes les 5 minutes va s’empiler. Utilisez flock pour garantir une seule instance a la fois.
Tester uniquement en interactif : le script marche quand vous le lancez, mais pas en cron. Testez avec env -i bash -c "/chemin/script.sh" pour simuler l’environnement cron reduit.
Jour de la semaine et jour du mois conflit : si vous mettez 0 0 15 * 1, cron declenche le 15 du mois OU le lundi (OR, pas AND). Pour une vraie combinaison, filtrez dans le script.
Crontab plein de taches silencieuses : au bout d’un an, personne ne sait ce qu’elles font. Documentez chaque ligne avec un commentaire et centralisez la liste dans Git.
Checklist
Service cron actif et active au demarrage (systemctl enable cron).
Syntaxe crontab maitrisee : minute, heure, jour_mois, mois, jour_semaine.
Chemins absolus utilises dans toutes les commandes.
Variables PATH et SHELL definies en haut du crontab.
Sortie et erreurs redirigees avec >> log 2>&1.
Scripts testes manuellement avant planification.
Scripts testes en environnement minimal env -i bash -c.
flock utilise pour empecher les executions concurrentes.
Rotation des logs configuree (logrotate).
Rotation des sauvegardes incluse dans le script (find -mtime -delete).
Chaque ligne du crontab documentee par un commentaire.
Sauvegarde du crontab versionnee dans Git.
Monitoring externe type healthchecks.io pour etre alerte en cas d’echec.
Logs consultes regulierement : grep CRON /var/log/syslog.
Systemd timers consideres pour les cas complexes (dependances, catch-up).