AI-TOL
📚 Complete Guide 🕐 25 Minuten 📊 Mittelstufe ✓ Updated 2026-02-28

Cron-Ausdruck Vollständiger Leitfaden | Von Grundlagen bis Fortgeschrittene

Umfassende Anleitung zu Cron-Ausdruck-Syntax mit 10 Praxisbeispielen, Debugging-Techniken, Best Practices und FAQ. Beherrschen Sie Linux-Zeitplanungsaufgaben.

Learn by doing

Practice with the while reading - free, no registration required

Open →

Real-World Examples

Case Study 1: Automatisierte Datenbanksicherung

Problem

Ein Startup benötigte zuverlässige tägliche PostgreSQL-Sicherungen. Die ersten Versuche schlugen fehl, Cron-Protokolle zeigten "command not found"-Fehler.

Solution

Das Problem lag daran, dass pg_dump Umgebungsvariablen benötigte und das Skript relative Pfade verwendete. Die Lösung bestand darin, Umgebungsvariablen am Anfang des Skripts zu setzen, absolute Pfade zu verwenden, Protokollierung und Fehlerbehandlung hinzuzufügen:


                  #!/bin/bash
# Datenbank-Sicherungsskript

# Umgebungsvariablen
export PGPASSWORD='your_password'
export PATH=/usr/local/bin:/usr/bin:/bin

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

# Sicherung erstellen
/usr/bin/pg_dump -h localhost -U postgres "$DB_NAME" > "$BACKUP_FILE" 2>&1

# Erfolg prüfen
if [ $? -eq 0 ]; then
  echo "Sicherung erfolgreich: $BACKUP_FILE" >> /var/log/db_backup.log
  # Behalte Sicherungen der letzten 7 Tage
  find "$BACKUP_DIR" -name "${DB_NAME}_*.sql" -mtime +7 -delete
else
  echo "Sicherung fehlgeschlagen, Fehlermeldungen prüfen" >> /var/log/db_backup.log
  exit 1
fi
                

Case Study 2: Mikroservice-Health-Check

Problem

Ein in Kubernetes bereitgestellter Mikroservice benötigte regelmäßige Health-Checks. Der Service blieb manchmal hängen und benötigte einen automatischen Neustart.

Solution

Kubernetes CronJob-Ressource erstellen, die regelmäßig den Health-Check-Endpunkt aufruft:


                  apiVersion: batch/v1
kind: CronJob
metadata:
  name: health-check
spec:
  schedule: "*/5 * * * *"  # Alle 5 Minuten
  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 "Health-Check fehlgeschlagen, HTTP-Status: $response"
                # Neustart auslösen
                kubectl rollout restart deployment/my-service
              fi
          restartPolicy: OnFailure
                

Case Study 3: Protokollrotation und -archivierung

Problem

Webserver-Protokolldateien wuchsen schnell, Speicherplatz reichte oft nicht aus. Automatische Rotation, Komprimierung und Bereinigung waren erforderlich.

Solution

logrotate mit cron für Protokollmanagement verwenden:


                  /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
    # Komprimierte Protokolle älter als 7 Tage in Archiv verschieben
    find /var/log/nginx -name "*.gz" -mtime +7 -exec mv {} /archive/nginx/ \;
  endaction
}

# Cron-Aufgabe (logrotate erstellt automatisch)
0 0 * * * /usr/sbin/logrotate -f /etc/logrotate.conf
                

Case Study 4: Zeitgeplante E-Mail-Berichte

Problem

Die Finanzabteilung benötigte jeden Morgen um 8 Uhr einen Umsatzbericht des Vortags per E-Mail.

Solution

Skript erstellen, das Berichte generiert und per E-Mail sendet:


                  #!/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():
    """Umsatzbericht generieren"""
    yesterday = datetime.now() - timedelta(days=1)
    date_str = yesterday.strftime('%Y-%m-%d')

    # SQL-Abfrage ausführen
    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):
    """E-Mail senden"""
    msg = MIMEMultipart()
    msg['From'] = '[email protected]'
    msg['To'] = '[email protected]'
    msg['Subject'] = f'Umsatzbericht - {datetime.now().strftime("%Y-%m-%d")}'

    body = f'''
    Umsatzbericht
    {'='*40}

    {report}

    {'='*40}
    Diese E-Mail wurde automatisch erstellt, bitte nicht antworten.
    '''
    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 verteilter zeitgeplanter Aufgaben

Problem

Auf mehreren Servern laufende zeitgeplante Aufgaben mussten sicherstellen, dass zur gleichen Zeit nur eine ausführt wird, um doppelte Verarbeitung zu vermeiden.

Solution

Verteilte Sperre verwenden, um gegenseitigen Ausschluss zu gewährleisten:


                  #!/bin/bash
# Verteilte Datenverarbeitungsaufgabe

LOCK_FILE="/tmp/data_processing.lock"
LOCK_TIMEOUT=3600  # 1 Stunde Timeout
REDIS_HOST="redis.internal"

# Sperre erwerben
acquire_lock() {
  redis-cli -h "$REDIS_HOST" SETNX "$LOCK_FILE" "$HOSTNAME:$$" > /dev/null
  return $?
}

# Sperre freigeben
release_lock() {
  redis-cli -h "$REDIS_HOST" DEL "$LOCK_FILE" > /dev/null
}

# Hauptlogik
main() {
  echo "Datenverarbeitung starten..."

  # Prüfen, ob Sperre abgelaufen
  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 "Sperre abgelaufen, erzwinge Erwerb"
      release_lock
    fi
  fi

  # Versuch, Sperre zu erwerben
  if ! acquire_lock; then
    owner=$(redis-cli -h "$REDIS_HOST" GET "$LOCK_FILE")
    echo "Aufgabe läuft bereits: $owner"
    exit 0
  fi

  # Sperren-Timeout setzen
  redis-cli -h "$REDIS_HOST" SETEX "$LOCK_FILE.ttl" "$LOCK_TIMEOUT" "$(date +%s)" > /dev/null

  # Aufgabe ausführen
  python3 /scripts/process_data.py

  # Sperre freigeben
  release_lock

  echo "Datenverarbeitung abgeschlossen"
}

# Ausführung
main
                

Case Study 6: Schrittweise Bereitstellung

Problem

Alle Server müssen ohne Service-Unterbrechung schrittweise aktualisiert werden, je 5 Server im Abstand von 2 Minuten.

Solution

Cron-gesteuertes schrittweises Bereitstellungssystem:


                  #!/bin/bash
# Skript für schrittweise Bereitstellung

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 Minuten

# Serverliste abrufen
servers=$(jq -r '.servers[]' "$DEPLOYMENT_CONFIG")
total_servers=$(echo "$servers" | wc -l)

# Aktuelles Batch berechnen
start=$((CURRENT_BATCH * BATCH_SIZE))
end=$((start + BATCH_SIZE))

echo "Starte Bereitstellung Batch $((CURRENT_BATCH + 1)), Server $start-$end"

# Aktuelles Batch bereitstellen
echo "$servers" | sed -n "${start},${end}p" | while read server; do
  echo "Bereitstellung auf $server ..."
  ssh "$server" 'bash -s' < /scripts/update_service.sh
done

# Fortschritt speichern
if [ $end -lt $total_servers ]; then
  echo $((CURRENT_BATCH + 1)) > /var/run/deployment_batch
  echo "Batch abgeschlossen, warte auf nächstes..."
else
  echo "Alle Batches bereitgestellt"
  rm -f /var/run/deployment_batch
fi
                

Case Study 7: Automatische Zertifikatserneuerung

Problem

SSL-Zertifikate müssen alle 90 Tage erneuert werden, manuelle Vorgänge werden vergessen und verursachen Service-Unterbrechungen.

Solution

Let's Encrypt automatische Erneuerung verwenden:


                  #!/bin/bash
# Automatische SSL-Zertifikatserneuerung

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"
}

# Zertifikatsablauf prüfen
check_cert_expiry() {
  local domain=$1
  local cert_file="$CERT_DIR/$domain/cert.pem"

  if [ ! -f "$cert_file" ]; then
    log "Zertifikat nicht vorhanden: $domain"
    return 1
  fi

  # Verbleibende Tage berechnen
  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
}

# Zertifikat erneuern
renew_cert() {
  log "Beginne Zertifikatserneuerung: $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 "Zertifikat erfolgreich erneuert"

    # nginx neu laden
    systemctl reload nginx

    # Benachrichtigung senden
    echo "Zertifikat erfolgreich erneuert" | mail -s "Zertifikatserneuerung" "$EMAIL"
  else
    log "Zertifikatserneuerung fehlgeschlagen"
    echo "Zertifikatserneuerung fehlgeschlagen, Protokolle prüfen" | mail -s "Erneuerung fehlgeschlagen" "$EMAIL"
    exit 1
  fi
}

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

  if [ $days_left -lt 30 ]; then
    log "Zertifikat läuft in $days_left Tagen ab, beginne Erneuerung"
    renew_cert
  else
    log "Zertifikat hat noch $days_left Tage, keine Erneuerung nötig"
  fi
done
                

Case Study 8: Cache-Vorwärmung

Problem

E-Commerce-Website hatte während Spitzenlastzeiten niedrige Cache-Trefferquoten, benötigte Vorwärmung vor Spitzenlast.

Solution

Automatische Vorwärmung beliebter Produkt-Caches vor Spitzenlast:


                  #!/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():
    """Beliebte Produkte abrufen"""
    response = requests.get(f"{API_BASE}/analytics/popular", params={
      'limit': 1000,
      'time_range': '24h'
    })
    return response.json()['products']

def warmup_cache(product_ids):
    """Cache vorwärmen"""
    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"Vorwärmung erfolgreich: {len(chunk)} Produkte")
        else:
          print(f"Vorwärmung fehlgeschlagen: {response.text}")
      except Exception as e:
        print(f"Vorwärmungsfehler: {e}")

def main():
  print(f"[{datetime.now()}] Cache-Vorwärmung starten")

  try:
    # Beliebte Produkte abrufen
    products = get_popular_products()
    product_ids = [p['id'] for p in products]

    print(f"{len(product_ids)} beliebte Produkte abgerufen")

    # Cache vorwärmen
    warmup_cache(product_ids)

    print(f"[{datetime.now()}] Cache-Vorwärmung abgeschlossen")

  except Exception as e:
    print(f"Vorwärmung fehlgeschlagen: {e}")
    exit 1)

if __name__ == '__main__':
  main()
                

Case Study 9: Datensynchronisation und -bereinigung

Problem

Anonymisierte Produktdaten mussten in Testumgebung synchronisiert werden, wobei nur die letzten 30 Tage erhalten blieben.

Solution

Datensynchronisations- und Bereinigungsskript erstellen:


                  #!/bin/bash
# Datenbanksynchronisation mit Testumgebung

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

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

# Produktdaten exportieren (anonymisiert)
dump_data() {
  log "Produktdatenexport starten..."

  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

  # Anonymisierung
  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 "Datenexport und Anonymisierung abgeschlossen"
}

# In Testumgebung importieren
import_data() {
  log "Import in Testumgebung starten..."

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

  log "Datenimport abgeschlossen"
}

# Temporäre Dateien bereinigen
cleanup() {
  log "Temporäre Dateien bereinigen..."
  rm -f /tmp/dump*.sql.gz
}

# Alte Testumgebungsdaten bereinigen
cleanup_old_data() {
  log "Alte Testumgebungsdaten bereinigen..."

  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 "Bereinigung alter Daten abgeschlossen"
}

# Hauptprozess
main() {
  log "===== Datensynchronisation starten ====="

  dump_data
  import_data
  cleanup_old_data
  cleanup

  log "===== Datensynchronisation abgeschlossen ====="
}

main
                

Case Study 10: Überwachungs- und Alarmintegration

Problem

Bei Fehlschlagen zeitgeplanter Aufgaben muss das Betriebsteam sofort benachrichtigt werden, Integration in bestehendes Überwachungssystem erforderlich.

Solution

Prometheus und Alertmanager für Alarmintegration verwenden:


                  #!/bin/bash
# Aufgaben-Wrapper mit Überwachungsintegration

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"

# Initialisierung
START_TIME=$(date +%s)
echo "# HELP task_last_success_timestamp Letzte Erfolgszeit" > "$METRICS_FILE"
echo "# TYPE task_last_success_timestamp gauge" >> "$METRICS_FILE"

# Aufgabe ausführen
run_task() {
  echo "[$(date)] Aufgaben-Ausführung starten: $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)] Aufgabe erfolgreich, Dauer: ${DURATION}s" >> "$LOG_FILE"

    # Erfolgsmetrik protokollieren
    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)] Aufgabe fehlgeschlagen, Exit-Code: $EXIT_CODE" >> "$LOG_FILE"

    # Fehlermetrik protokollieren
    echo "task_last_success_timestamp{task="$TASK_NAME"} 0" >> "$METRICS_FILE"
    echo "task_duration_seconds{task="$TASK_NAME",status="failed"} $DURATION" >> "$METRICS_FILE"

    # Alarm senden
    curl -X POST http://alertmanager:9093/api/v1/alerts -d '[
      {
        "labels": {
          "alertname": "TaskFailed",
          "task": "'$TASK_NAME'",
          "severity": "critical"
        },
        "annotations": {
          "summary": "Aufgabe fehlgeschlagen: '$TASK_NAME'",
          "description": "Exit-Code: '$EXIT_CODE', Protokoll: '$LOG_FILE'"
        }
      }
    ]'

    exit 1
  fi
}

run_task
                

Best Practices

Verwenden Sie immer absolute Pfade

Leiten Sie Ausgaben in Protokolldateien um

PATH-Umgebungsvariable setzen

Shebang verwenden

Ausführungsberechtigungen hinzufügen

Testen Sie komplexe Ausdrücke

Master Today

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

Try →