AI-TOL
📚 Complete Guide 🕐 25 minutes 📊 Intermédiaire ✓ Updated 2026-02-28

Guide Complet des Expressions Cron | Des Bases aux Techniques Avancées

Guide complet de la syntaxe des expressions Cron avec 10 exemples réels, techniques de débogage, meilleures pratiques et FAQ. Maîtrisez les tâches planifiées Linux.

Learn by doing

Practice with the while reading - free, no registration required

Open →

Real-World Examples

Case Study 1: Sauvegarde de base de données automatisée

Problem

Une startup avait besoin de sauvegardes PostgreSQL quotidiennes fiables. Les premières tentatives ont échoué, les journaux cron montraient des erreurs "command not found".

Solution

Le problème était que pg_dump nécessitait des variables d'environnement et que le script utilisait des chemins relatifs. La solution consistait à définir les variables d'environnement au début du script, utiliser des chemins absolus, ajouter la journalisation et la gestion des erreurs :


                  #!/bin/bash
# Script de sauvegarde de base de données

# Variables d'environnement
export PGPASSWORD='your_password'
export PATH=/usr/local/bin:/usr/bin:/bin

# Configuration
DB_NAME="mydb"
BACKUP_DIR="/backups"
DATE=$(date +%Y%m%d_%H%M%S)
BACKUP_FILE="$BACKUP_DIR/${DB_NAME}_${DATE}.sql"

# Créer la sauvegarde
/usr/bin/pg_dump -h localhost -U postgres "$DB_NAME" > "$BACKUP_FILE" 2>&1

# Vérifier le succès
if [ $? -eq 0 ]; then
  echo "Sauvegarde réussie: $BACKUP_FILE" >> /var/log/db_backup.log
  # Conserver les sauvegardes des 7 derniers jours
  find "$BACKUP_DIR" -name "${DB_NAME}_*.sql" -mtime +7 -delete
else
  echo "Sauvegarde échouée, vérifiez les messages d'erreur" >> /var/log/db_backup.log
  exit 1
fi
                

Case Study 2: Vérification de santé des microservices

Problem

Un microservice déployé sur Kubernetes nécessitait des vérifications de santé régulières. Le service se bloquait parfois et nécessitait un redémarrage automatique.

Solution

Créer une ressource Kubernetes CronJob qui appelle régulièrement le endpoint de santé :


                  apiVersion: batch/v1
kind: CronJob
metadata:
  name: health-check
spec:
  schedule: "*/5 * * * *"  # Toutes les 5 minutes
  successfulJobsHistoryLimit: 3
  failedJobsHistoryLimit: 3
  jobTemplate:
    spec:
      template:
        spec:
          containers:
          - name: health-check
            image: curlimages/curl:latest
            imagePullPolicy: Always
            command:
            - /bin/sh
            - -c
            - |-
              response=$(curl -s -o /dev/null -w "%{http_code}" http://service:8080/health)
              if [ $response -ne 200 ]; then
                echo "Vérification de santé échouée, HTTP Status: $response"
                # Déclencher la logique de redémarrage
                kubectl rollout restart deployment/my-service
              fi
          restartPolicy: OnFailure
                

Case Study 3: Rotation et archivage des journaux

Problem

Les fichiers journaux du serveur web augmentaient rapidement, l'espace disque était souvent insuffisant. Une rotation, compression et nettoyage automatiques des journaux étaient nécessaires.

Solution

Utiliser logrotate avec cron pour la gestion des journaux :


                  /var/log/nginx/*.log {
  daily
  missingok
  rotate 14
  compress
  delaycompress
  notifempty
  create 0640 www-data adm
  sharedscripts
  postrotate
    [ -f /var/run/nginx.pid ] && kill -USR1 $(cat /var/run/nginx.pid)
  endscript
  lastaction
    # Déplacer les journaux compressés de plus de 7 jours vers l'archive
    find /var/log/nginx -name "*.gz" -mtime +7 -exec mv {} /archive/nginx/ \;
  endaction
}

# Tâche cron (logrotate crée automatiquement)
0 0 * * * /usr/sbin/logrotate -f /etc/logrotate.conf
                

Case Study 4: Rapports par email planifiés

Problem

Le service financier devait recevoir un rapport de revenus de la veille par email chaque matin à 8h.

Solution

Créer un script qui génère le rapport et l'envoie par email :


                  #!/usr/bin/env python3
import smtplib
from email.mime.text import MIMEText
from email.mime.multipart import MIMEMultipart
import subprocess
from datetime import datetime, timedelta

def generate_report():
    """Générer le rapport de revenus"""
    yesterday = datetime.now() - timedelta(days=1)
    date_str = yesterday.strftime('%Y-%m-%d')

    # Exécuter la requête SQL
    cmd = f'''
    mysql -u reporter -ppassword -h db.internal -e "
    SELECT product, SUM(amount) as revenue
    FROM sales
    WHERE DATE(created_at) = '{date_str}'
    GROUP BY product
    "
    '''
    result = subprocess.run(cmd, shell=True, capture_output=True, text=True)
    return result.stdout

def send_email(report):
    """Envoyer l'email"""
    msg = MIMEMultipart()
    msg['From'] = '[email protected]'
    msg['To'] = '[email protected]'
    msg['Subject'] = f'Rapport de revenus - {datetime.now().strftime("%Y-%m-%d")}'

    body = f'''
    Rapport de revenus
    {'='*40}

    {report}

    {'='*40}
    Cet email est généré automatiquement, ne pas répondre.
    '''
    msg.attach(MIMEText(body, 'plain'))

    with smtplib.SMTP('smtp.company.com', 587) as server:
        server.starttls()
        server.login('[email protected]', 'password')
        server.send_message(msg)

if __name__ == '__main__':
    report = generate_report()
    send_email(report)
                

Case Study 5: Synchronisation des tâches planifiées distribuées

Problem

Les tâches planifiées s'exécutant sur plusieurs serveurs devaient s'assurer qu'un seul serveur s'exécute à la fois pour éviter le traitement en double.

Solution

Utiliser un verrou distribué pour assurer l'exclusion mutuelle :


                  #!/bin/bash
# Tâche de traitement de données distribué

LOCK_FILE="/tmp/data_processing.lock"
LOCK_TIMEOUT=3600  # 1 heure de timeout
REDIS_HOST="redis.internal"

# Acquérir le verrou
acquire_lock() {
  redis-cli -h "$REDIS_HOST" SETNX "$LOCK_FILE" "$HOSTNAME:$$" > /dev/null
  return $?
}

# Libérer le verrou
release_lock() {
  redis-cli -h "$REDIS_HOST" DEL "$LOCK_FILE" > /dev/null
}

# Logique principale
main() {
  echo "Démarrage du traitement des données..."

  # Vérifier si le verrou a expiré
  lock_time=$(redis-cli -h "$REDIS_HOST" GET "$LOCK_FILE.ttl")
  if [ -n "$lock_time" ]; then
    current_time=$(date +%s)
    if [ $((current_time - lock_time)) -gt $LOCK_TIMEOUT ]; then
      echo "Verrou expiré, acquisition forcée"
      release_lock
    fi
  fi

  # Tenter d'acquérir le verrou
  if ! acquire_lock; then
    owner=$(redis-cli -h "$REDIS_HOST" GET "$LOCK_FILE")
    echo "Tâche déjà en cours: $owner"
    exit 0
  fi

  # Définir le timeout du verrou
  redis-cli -h "$REDIS_HOST" SETEX "$LOCK_FILE.ttl" "$LOCK_TIMEOUT" "$(date +%s)" > /dev/null

  # Exécuter la tâche
  python3 /scripts/process_data.py

  # Libérer le verrou
  release_lock

  echo "Traitement des données terminé"
}

# Exécution
main
                

Case Study 6: Déploiement progressif

Problem

Tous les serveurs devaient être mis à jour progressivement sans interruption de service, 5 serveurs à la fois, à 2 minutes d'intervalle.

Solution

Système de déploiement progressif déclenché par Cron :


                  #!/bin/bash
# Script de déploiement progressif

DEPLOYMENT_CONFIG="/etc/deployment/config.json"
CURRENT_BATCH=$(cat /var/run/deployment_batch 2>/dev/null || echo 0)
BATCH_SIZE=5
BATCH_DELAY=120  # 2 minutes

# Obtenir la liste des serveurs
servers=$(jq -r '.servers[]' "$DEPLOYMENT_CONFIG")
total_servers=$(echo "$servers" | wc -l)

# Calculer le batch actuel
start=$((CURRENT_BATCH * BATCH_SIZE))
end=$((start + BATCH_SIZE))

echo "Début du déploiement batch $((CURRENT_BATCH + 1)), serveurs $start-$end"

# Déployer le batch actuel
echo "$servers" | sed -n "${start},${end}p" | while read server; do
  echo "Déploiement sur $server ..."
  ssh "$server" 'bash -s' < /scripts/update_service.sh
done

# Enregistrer la progression
if [ $end -lt $total_servers ]; then
  echo $((CURRENT_BATCH + 1)) > /var/run/deployment_batch
  echo "Batch terminé, attente du prochain..."
else
  echo "Tous les batches déployés"
  rm -f /var/run/deployment_batch
fi
                

Case Study 7: Renouvellement automatique de certificats

Problem

Les certificats SSL devaient être renouvelés tous les 90 jours, les procédures manuelles étaient oubliées et causaient des interruptions de service.

Solution

Utiliser le renouvellement automatique Let's Encrypt :


                  #!/bin/bash
# Renouvellement automatique de certificat SSL

DOMAINS="example.com www.example.com api.example.com"
EMAIL="[email protected]"
CERT_DIR="/etc/letsencrypt/live"
LOG_FILE="/var/log/cert_renewal.log"

log() {
  echo "[$(date '+%Y-%m-%d %H:%M:%S')] $1" >> "$LOG_FILE"
}

# Vérifier l'expiration du certificat
check_cert_expiry() {
  local domain=$1
  local cert_file="$CERT_DIR/$domain/cert.pem"

  if [ ! -f "$cert_file" ]; then
    log "Certificat non trouvé: $domain"
    return 1
  fi

  # Calculer les jours restants
  expiry_date=$(openssl x509 -enddate -noout -in "$cert_file" | cut -d= -f2)
  expiry_epoch=$(date -d "$expiry_date" +%s)
  current_epoch=$(date +%s)
  days_left=$(( (expiry_epoch - current_epoch) / 86400 ))

  echo $days_left
}

# Renouveler le certificat
renew_cert() {
  log "Début du renouvellement du certificat: $DOMAINS"

  certbot certonly --non-interactive --agree-tos     --email "$EMAIL"     --webroot     -w /var/www/html     -d $DOMAINS     >> "$LOG_FILE" 2>&1

  if [ $? -eq 0 ]; then
    log "Certificat renouvelé avec succès"

    # Recharger nginx
    systemctl reload nginx

    # Envoyer une notification
    echo "Certificat renouvelé avec succès" | mail -s "Renouvellement de certificat" "$EMAIL"
  else
    log "Renouvellement du certificat échoué"
    echo "Renouvellement du certificat échoué, vérifiez les journaux" | mail -s "Renouvellement échoué" "$EMAIL"
    exit 1
  fi
}

# Logique principale
for domain in $DOMAINS; do
  days_left=$(check_cert_expiry "$domain")

  if [ $days_left -lt 30 ]; then
    log "Le certificat expire dans $days_left jours, début du renouvellement"
    renew_cert
  else
    log "Le certificat a encore $days_left jours, pas de renouvellement nécessaire"
  fi
done
                

Case Study 8: Préchauffage du cache

Problem

Le site e-commerce avait un taux de réussite du cache faible pendant les périodes de pointe, nécessitant un préchauffage avant la pointe.

Solution

Préchauffer automatiquement le cache des produits populaires avant la pointe :


                  #!/usr/bin/env python3
import requests
import json
from datetime import datetime

API_BASE = "https://api.example.com"
CACHE_ENDPOINT = f"{API_BASE}/cache/warmup"

def get_popular_products():
    """Obtenir les produits populaires"""
    response = requests.get(f"{API_BASE}/analytics/popular", params={
      'limit': 1000,
      'time_range': '24h'
    })
    return response.json()['products']

def warmup_cache(product_ids):
    """Préchauffer le cache"""
    chunks = [product_ids[i:i+50] for i in range(0, len(product_ids), 50)]

    for chunk in chunks:
      try:
        response = requests.post(CACHE_ENDPOINT, json={
          'product_ids': chunk,
          'ttl': 3600
        }, timeout=30)

        if response.status_code == 200:
          print(f"Préchauffage réussi: {len(chunk)} produits")
        else:
          print(f"Préchauffage échoué: {response.text}")
      except Exception as e:
        print(f"Erreur de préchauffage: {e}")

def main():
  print(f"[{datetime.now()}] Début du préchauffage du cache")

  try:
    # Obtenir les produits populaires
    products = get_popular_products()
    product_ids = [p['id'] for p in products]

    print(f"{len(product_ids)} produits populaires obtenus")

    # Préchauffer le cache
    warmup_cache(product_ids)

    print(f"[{datetime.now()}] Préchauffage du cache terminé")

  except Exception as e:
    print(f"Préchauffage échoué: {e}")
    exit 1

if __name__ == '__main__':
  main()
                

Case Study 9: Synchronisation et nettoyage des données

Problem

Les données de production anonymisées devaient être synchronisées avec l'environnement de test, en ne conservant que les 30 derniers jours.

Solution

Créer un script de synchronisation et de nettoyage des données :


                  #!/bin/bash
# Synchronisation de base de données vers l'environnement de test

PROD_DB="production"
TEST_DB="test_staging"
RETENTION_DAYS=30

log() {
  echo "[$(date '+%Y-%m-%d %H:%M:%S')] $1"
}

# Exporter les données de production (anonymisées)
dump_data() {
  log "Début de l'export des données de production..."

  mysqldump -h prod-db.internal -u exporter -ppassword \
    --single-transaction \
    --quick \
    --lock-tables=false \
    --where="DATE(created_at) >= DATE(NOW()) - INTERVAL $RETENTION_DAYS DAY" \
    "$PROD_DB" \
    users orders products \
    | gzip > /tmp/dump.sql.gz

  # Anonymisation
  zcat /tmp/dump.sql.gz | sed \
    -e 's/"\(email\|phone\|ssn\)":"[^"]*"/"\1":"***"/g' \
    -e 's/"\(credit_card\|password\)":"[^"]*"/"\1":"***"/g' \
    | gzip > /tmp/dump_anon.sql.gz

  log "Export et anonymisation des données terminés"
}

# Importer dans l'environnement de test
import_data() {
  log "Début de l'import dans l'environnement de test..."

  gunzip < /tmp/dump_anon.sql.gz | mysql -h test-db.internal -u importer -ppassword "$TEST_DB"

  log "Import des données terminé"
}

# Nettoyer les fichiers temporaires
cleanup() {
  log "Nettoyage des fichiers temporaires..."
  rm -f /tmp/dump*.sql.gz
}

# Nettoyer les anciennes données de test
cleanup_old_data() {
  log "Nettoyage des anciennes données de test..."

  mysql -h test-db.internal -u admin -ppassword "$TEST_DB" <<EOF
DELETE FROM orders WHERE DATE(created_at) < DATE(NOW()) - INTERVAL $RETENTION_DAYS DAY;
DELETE FROM audit_logs WHERE DATE(created_at) < DATE(NOW()) - INTERVAL $RETENTION_DAYS DAY;
OPTIMIZE TABLE users, orders, products;
EOF

  log "Nettoyage des anciennes données terminé"
}

# Processus principal
main() {
  log "===== Début de la synchronisation des données ====="

  dump_data
  import_data
  cleanup_old_data
  cleanup

  log "===== Synchronisation des données terminée ====="
}

main
                

Case Study 10: Intégration de la surveillance et des alertes

Problem

Lors de l'échec des tâches planifiées, l'équipe des opérations devait être notifiée immédiatement, une intégration avec le système de surveillance existant était nécessaire.

Solution

Utiliser Prometheus et Alertmanager pour l'intégration des alertes :


                  #!/bin/bash
# Wrapper de tâche avec intégration de surveillance

TASK_NAME="data_import"
TASK_COMMAND="/usr/bin/python3 /scripts/import.py"
LOG_FILE="/var/log/tasks/${TASK_NAME}.log"
METRICS_FILE="/var/lib/node_exporter/textfile_collector/${TASK_NAME}.prom"

# Initialisation
START_TIME=$(date +%s)
echo "# HELP task_last_success_timestamp Dernière heure de succès" > "$METRICS_FILE"
echo "# TYPE task_last_success_timestamp gauge" >> "$METRICS_FILE"

# Exécuter la tâche
run_task() {
  echo "[$(date)] Début de l'exécution de la tâche: $TASK_NAME" >> "$LOG_FILE"

  $TASK_COMMAND >> "$LOG_FILE" 2>&1
  EXIT_CODE=$?

  END_TIME=$(date +%s)
  DURATION=$((END_TIME - START_TIME))

  if [ $EXIT_CODE -eq 0 ]; then
    echo "[$(date)] Tâche réussie, durée: ${DURATION}s" >> "$LOG_FILE"

    # Enregistrer la métrique de succès
    echo "task_last_success_timestamp{task="$TASK_NAME"} $END_TIME" >> "$METRICS_FILE"
    echo "task_duration_seconds{task="$TASK_NAME",status="success"} $DURATION" >> "$METRICS_FILE"
  else
    echo "[$(date)] Tâche échouée, code de sortie: $EXIT_CODE" >> "$LOG_FILE"

    # Enregistrer la métrique d'échec
    echo "task_last_success_timestamp{task="$TASK_NAME"} 0" >> "$METRICS_FILE"
    echo "task_duration_seconds{task="$TASK_NAME",status="failed"} $DURATION" >> "$METRICS_FILE"

    # Envoyer une alerte
    curl -X POST http://alertmanager:9093/api/v1/alerts -d '[
      {
        "labels": {
          "alertname": "TaskFailed",
          "task": "'$TASK_NAME'",
          "severity": "critical"
        },
        "annotations": {
          "summary": "Tâche échouée: '$TASK_NAME'",
          "description": "Code de sortie: '$EXIT_CODE', journal: '$LOG_FILE'"
        }
      }
    ]'

    exit 1
  fi
}

run_task
                

Best Practices

Utilisez toujours des chemins absolus

Redirigez la sortie vers des fichiers journal

Définissez la variable PATH

Utilisez un shebang

Ajoutez les permissions d'exécution

Testez les expressions complexes

Master Today

Put your knowledge into practice with our free, privacy-focused tools

Try →