Cronjobs vor Ueberlappung schuetzen: Locking mit flock in der Praxis
AI generated
$
/etc
Linux · flock · Cron · Server-Administration
Cronjobs vor Ueberlappung schuetzen
Locking mit flock in der Praxis

Ein Cronjob, der laenger laeuft als das geplante Intervall, startet still ein zweites Mal, obwohl der erste Lauf noch nicht fertig ist. Zwei parallele Datenbank-Exports, zwei gleichzeitige Backup-Prozesse oder zwei sich gegenseitig blockierende Import-Skripte sind die Folge, oft ohne sofort sichtbare Fehlermeldung. Dieser Artikel zeigt, wie flock ueberlappende Cronjobs zuverlaessig verhindert, sowohl direkt in der Crontab als auch innerhalb von Skripten, und wo die Grenzen einfacherer Locking-Ansaetze liegen.

16 Min. Lesezeit flock · Cron · Locking · Dateideskriptoren Debian · Ubuntu · RHEL · util-linux

1. Warum ueberlappende Cronjobs ein reales Betriebsrisiko sind

Cron geht implizit davon aus, dass ein Job innerhalb seines geplanten Intervalls fertig wird. Diese Annahme haelt in der Praxis nicht immer: Ein taeglicher Datenbank-Export, der normalerweise zehn Minuten dauert, kann bei wachsendem Datenbestand irgendwann laenger brauchen als bis zum naechsten geplanten Lauf. Cron startet den naechsten Durchlauf trotzdem puenktlich, ohne zu pruefen, ob der vorherige noch aktiv ist. Das Ergebnis sind zwei parallel laufende Instanzen desselben Jobs, die um dieselben Ressourcen konkurrieren.

Besonders kritisch wird Ueberlappung bei Jobs, die schreibend auf gemeinsame Ressourcen zugreifen, etwa Backup-Skripte, die dieselbe Zieldatei beschreiben, oder Import-Prozesse, die dieselben Datenbanktabellen bearbeiten. Im besten Fall verlangsamen sich beide Instanzen gegenseitig. Im schlechteren Fall entstehen inkonsistente Daten, doppelte Eintraege oder ein Deadlock, der beide Prozesse dauerhaft blockiert, bis ein Administrator manuell eingreift. Locking ist deshalb keine Kosmetik, sondern eine Grundvoraussetzung fuer robuste Cronjobs mit variabler Laufzeit.

2. Wie Ueberlappung entsteht: Laufzeiten, Lastspitzen, haengende Prozesse

Drei Szenarien fuehren in der Praxis am haeufigsten zu ueberlappenden Cronjobs. Erstens wachsende Datenmengen: Ein Job, der bei der Einfuehrung in wenigen Minuten fertig war, braucht Monate spaeter deutlich laenger, ohne dass jemand die Cron-Zeile entsprechend anpasst. Zweitens externe Abhaengigkeiten: Ein Skript, das auf eine langsame API oder einen ueberlasteten Datenbankserver wartet, kann unvorhersehbar lange blockieren, weit ueber die normale Laufzeit hinaus.

Drittens haengende Prozesse: Ein Skript, das durch einen Bug in eine Endlosschleife geraet oder auf eine nie eintreffende Netzwerkantwort wartet, blockiert unbegrenzt, waehrend Cron treu weiter neue Instanzen startet. Nach einigen Tagen koennen so Dutzende Zombie-aehnliche Prozesse parallel laufen, jeder mit eigenem Speicherverbrauch und eigenen offenen Datenbankverbindungen, bis der Server an seine Ressourcengrenzen stoesst. Genau dieses Szenario macht Locking zur Pflicht, nicht zur Option, sobald ein Cronjob produktiv eingesetzt wird.

3. flock Grundlagen: exklusive und geteilte Sperren

Das Kommando flock nutzt Advisory Locks auf Dateisystemebene, also Sperren, die kooperierende Prozesse respektieren, aber keinen Zugriff auf Betriebssystemebene erzwingen. Eine exklusive Sperre, die Standardeinstellung von flock, erlaubt nur einem einzigen Prozess gleichzeitig Zugriff auf eine bestimmte Datei als Lock-Objekt. Ein zweiter Prozess, der versucht, dieselbe Sperre zu erhalten, wartet entweder, bis die erste Sperre freigegeben wird, oder bricht sofort ab, je nach gewaehlter Option.

Die Option -n beziehungsweise --nonblock ist fuer Cronjobs die entscheidende Einstellung: Statt zu warten, bricht flock sofort ab, wenn die Sperre bereits vergeben ist, und gibt einen Exit-Code ungleich null zurueck. Genau dieses Verhalten verhindert Ueberlappung, weil der zweite, verfruehte Cron-Lauf sofort erkennt, dass der vorherige noch aktiv ist, und sich beendet, statt in eine Warteschlange einzureihen und die Situation weiter zu verschaerfen.


# Basic flock usage: exclusive, non-blocking lock on a lock file
flock -n /var/lock/backup.lock -c "/usr/local/bin/backup.sh"

# Exit code 1 means the lock was already held — the job simply skips this run
echo "Exit code: $?"

4. flock direkt in der Crontab einsetzen

Der einfachste und robusteste Einsatz von flock passiert direkt in der Crontab-Zeile, ohne das eigentliche Skript veraendern zu muessen. Man stellt dem eigentlichen Befehl einen flock-Aufruf mit Lock-Datei und der -n-Option voran. Laeuft der vorherige Job noch, bricht flock sofort ab, Cron protokolliert den fehlgeschlagenen Versuch, aber es entsteht keine zweite, konkurrierende Instanz.

Wichtig ist die Wahl eines eindeutigen Pfads fuer die Lock-Datei, typischerweise unterhalb von /var/lock/ oder /run/lock/, mit einem Namen, der eindeutig zum jeweiligen Job gehoert. Bei mehreren aehnlichen Cronjobs auf demselben Server ist es ein haeufiger Fehler, versehentlich dieselbe Lock-Datei fuer zwei voneinander unabhaengige Jobs zu verwenden, was dazu fuehrt, dass sich unabhaengige Aufgaben gegenseitig blockieren, obwohl sie inhaltlich gar nichts miteinander zu tun haben.


# /etc/cron.d/nightly-export — flock prevents overlapping runs directly in crontab
# Runs every 10 minutes, but only one instance can ever be active
*/10 * * * * appuser flock -n /var/lock/nightly-export.lock /usr/local/bin/export.sh

# Explicit per-job lock names avoid accidental cross-locking between unrelated jobs
0 2 * * * appuser flock -n /var/lock/db-backup.lock /usr/local/bin/db-backup.sh
0 3 * * * appuser flock -n /var/lock/log-cleanup.lock /usr/local/bin/log-cleanup.sh

5. flock im Skript selbst mit exec und Dateideskriptor

Fuer komplexere Faelle, etwa wenn ein Skript selbst entscheiden soll, wie es auf eine bereits vergebene Sperre reagiert, laesst sich flock auch innerhalb eines Bash-Skripts nutzen, ueber die Kombination aus exec und einem freien Dateideskriptor. Diese Variante oeffnet die Lock-Datei einmalig auf einem Deskriptor, typischerweise 200, und haelt die Sperre fuer die gesamte Laufzeit des Skripts, ohne einen externen flock-Prozess als Wrapper zu benoetigen.

Der Vorteil dieser Variante: Das Skript kann im Fall einer bereits vergebenen Sperre eigene Logik ausfuehren, etwa eine spezifische Log-Meldung schreiben oder ein Monitoring-System benachrichtigen, statt einfach nur mit einem generischen Exit-Code zu enden. Die Sperre wird automatisch freigegeben, sobald der Dateideskriptor beim Skriptende geschlossen wird, auch wenn das Skript durch einen Fehler oder ein Signal vorzeitig beendet wird.


#!/usr/bin/env bash
set -euo pipefail

LOCK_FILE="/var/lock/report-generation.lock"

# Open the lock file on file descriptor 200 and acquire an exclusive, non-blocking lock
exec 200>"$LOCK_FILE"
if ! flock -n 200; then
  echo "[INFO] Previous run still active, skipping this execution" >&2
  exit 0
fi

echo "[INFO] Lock acquired, starting report generation"
# ... actual job logic goes here ...

# Lock is released automatically when fd 200 closes at script exit

6. Die systemd-Alternative: automatischer Schutz vor Ueberlappung

Wer statt Cron systemd-Timer einsetzt, bekommt einen Grossteil dieses Problems bereits kostenlos geloest. Ein Service vom Typ oneshot, der von einem Timer ausgeloest wird, startet standardmaessig keine zweite Instanz, solange die erste noch laeuft, weil systemd den Aktivierungszustand des zugehoerigen Service-Units zentral verwaltet und einen bereits aktiven Dienst nicht doppelt startet. Das ersetzt einen manuellen Lock-Mechanismus fast vollstaendig, ohne dass man selbst flock einsetzen muss.

Fuer Faelle, in denen mehrere unterschiedliche Timer denselben zugrunde liegenden Vorgang nicht gleichzeitig ausloesen sollen, laesst sich zusaetzlich Conflicts= zwischen den Service-Units einsetzen, um gegenseitigen Ausschluss ueber Unit-Grenzen hinweg zu erzwingen. Fuer neue Automatisierungsvorhaben ist der Umstieg von Cron auf systemd-Timer deshalb oft der pragmatischere Weg, Ueberlappung von vornherein architektonisch auszuschliessen, statt sie nachtraeglich mit flock zu reparieren.

7. Ueberlappende Jobs erkennen: Monitoring und Alerting

Selbst mit funktionierendem Locking sollte man ueberwachen, wie oft ein Job tatsaechlich abgebrochen wird, weil die Sperre bereits vergeben war. Ein einzelner uebersprungener Lauf ist meist harmlos, eine wiederholte Haeufung deutet aber darauf hin, dass die geplante Laufzeit systematisch zu knapp bemessen ist und das zugrunde liegende Intervall oder die Skript-Performance ueberdacht werden muessen.

Praktisch laesst sich das ueber eine einfache Erweiterung des Skripts umsetzen, die jeden uebersprungenen Lauf in eine dedizierte Log-Datei schreibt oder einen Zaehler in einem Monitoring-System wie Prometheus erhoeht. Ein zusaetzlicher Watchdog-Check, der prueft, wie lange eine Lock-Datei bereits gehalten wird, hilft zudem, haengende Prozesse fruehzeitig zu erkennen, statt sie erst Tage spaeter beim naechsten manuellen Blick auf den Server zu bemerken.


#!/usr/bin/env bash
# Watchdog: alert if a lock has been held suspiciously long (possible hung process)
LOCK_FILE="/var/lock/nightly-export.lock"
MAX_AGE_MINUTES=60

if [[ -f "$LOCK_FILE" ]]; then
  age_minutes=$(( ($(date +%s) - $(stat -c %Y "$LOCK_FILE")) / 60 ))
  if (( age_minutes > MAX_AGE_MINUTES )); then
    echo "[ALERT] Lock held for ${age_minutes} minutes, possible hung process" >&2
    exit 1
  fi
fi

8. Haeufige Fehler beim Locking und wie man sie vermeidet

Der haeufigste Fehler ist die Verwendung von PID-Dateien statt flock. Ein Skript schreibt beim Start seine eigene Prozess-ID in eine Datei und prueft beim naechsten Lauf, ob dieser Prozess noch existiert. Das Problem: Nach einem harten Absturz oder Server-Neustart kann eine alte PID zufaellig von einem voellig anderen, neuen Prozess wiederverwendet werden, was zu einem falschen Positiv fuehrt und den Job dauerhaft blockiert, obwohl der urspruengliche Prozess laengst beendet ist.

flock umgeht dieses Problem grundsaetzlich, weil das Betriebssystem die Sperre automatisch freigibt, sobald der haltende Prozess beendet wird, unabhaengig davon, ob er normal endet, abstuerzt oder per Signal beendet wird. Ein zweiter haeufiger Fehler ist, die Lock-Datei manuell vor dem naechsten Lauf zu loeschen, in der Annahme, das sei notwendig. Das ist bei flock nicht noetig und kann sogar gefaehrlich sein, wenn die Datei geloescht wird, waehrend ein anderer Prozess noch aktiv auf sie wartet.

9. Locking-Strategien im Vergleich

Verschiedene Ansaetze zum Schutz vor Ueberlappung unterscheiden sich deutlich in Zuverlaessigkeit und Implementierungsaufwand.

Strategie Zuverlaessigkeit Aufwand Bewertung
Keine Sperre Keine Keiner Nicht produktionstauglich
PID-Datei Niedrig, PID-Wiederverwendung moeglich Mittel, eigene Logik noetig Veraltet, fehleranfaellig
flock Hoch, kernelverwaltet Gering, eine Zeile Empfohlener Standard
systemd oneshot Service Hoch, systemweit verwaltet Mittel, Unit-Dateien noetig Beste Wahl bei Neuentwicklung

Fuer bestehende Cron-basierte Infrastrukturen ist flock der pragmatischste Weg, sofortigen Schutz mit minimalem Aenderungsaufwand zu erreichen. Fuer neue Automatisierung lohnt sich oft der direkte Umstieg auf systemd-Timer mit oneshot-Services, weil dort Ueberlappungsschutz architektonisch eingebaut ist und nicht nachtraeglich ergaenzt werden muss.

Mironsoft

Linux-Server-Administration und Automatisierungs-Haertung

Eure Cronjobs vor Ueberlappung schuetzen?

Wir pruefen eure bestehenden Cronjobs auf Ueberlappungsrisiken, ruesten flock-basiertes Locking nach und richten Monitoring fuer haengende oder wiederholt uebersprungene Laeufe ein.

Audit

Bestehende Cronjobs auf fehlendes oder unsicheres Locking pruefen

Nachruesten

flock-Locking in Crontab und Skripten sauber implementieren

Monitoring

Alarmierung bei uebersprungenen und haengenden Laeufen aufbauen

10. Zusammenfassung

Ueberlappende Cronjobs entstehen, sobald die tatsaechliche Laufzeit eines Jobs das geplante Intervall ueberschreitet, sei es durch wachsende Datenmengen, langsame Abhaengigkeiten oder haengende Prozesse. flock loest dieses Problem zuverlaessig, indem es Advisory Locks auf Dateisystemebene nutzt, die das Betriebssystem automatisch freigibt, sobald der haltende Prozess endet, unabhaengig von der Art der Beendigung. Die Option -n sorgt dafuer, dass ein Job bei bereits vergebener Sperre sofort abbricht, statt zu warten und die Situation zu verschaerfen.

Direkt in der Crontab eingesetzt, schuetzt flock ohne jede Skriptaenderung. Innerhalb eines Skripts mit exec und Dateideskriptor lassen sich zusaetzlich eigene Reaktionen auf eine bereits vergebene Sperre implementieren. PID-Dateien sind der veraltete, fehleranfaellige Vorgaenger und sollten in neuem Code nicht mehr verwendet werden. Wer ohnehin auf systemd-Timer umsteigt, bekommt Ueberlappungsschutz durch oneshot-Services architektonisch eingebaut.

Cronjobs vor Ueberlappung schuetzen, das Wichtigste auf einen Blick

flock in Crontab

flock -n /var/lock/job.lock befehl verhindert Ueberlappung ohne jede Skriptaenderung.

flock im Skript

exec 200>lockdatei; flock -n 200 erlaubt eigene Reaktionen auf eine bereits vergebene Sperre.

Kein pidfile mehr

PID-Wiederverwendung nach Crashes macht pidfile-basiertes Locking unzuverlaessig. flock ist kernelverwaltet und sicher.

systemd als Alternative

oneshot-Services verhindern Ueberlappung automatisch, ganz ohne manuelles flock-Locking.

11. FAQ: Cronjobs vor Ueberlappung schuetzen mit flock

1Warum ueberlappen sich Cronjobs?
Cron startet strikt nach Zeitplan, unabhaengig vom Status des vorherigen Laufs. Bei zu langer Laufzeit laufen zwei Instanzen parallel.
2Wie verhindert flock Ueberlappung?
Advisory Lock auf einer Lock-Datei. Mit -n bricht ein zweiter Aufruf sofort ab, statt zu warten.
3flock in der Crontab einsetzen?
Befehl mit flock -n /pfad/lockdatei voranstellen. Keine Skriptaenderung noetig.
4flock vs. PID-Datei?
flock ist ein Kernel-Lock, automatisch freigegeben beim Prozessende. PID-Dateien sind fehleranfaellig durch PID-Wiederverwendung.
5Lock-Datei manuell loeschen?
Nicht noetig. Die Datei kann bestehen bleiben, nur die Sperre wird beim Prozessende freigegeben.
6flock im Bash-Skript nutzen?
exec 200>lockdatei, dann flock -n 200. Erlaubt eigene Reaktion auf bereits vergebene Sperre.
7Verhindert systemd Ueberlappung automatisch?
Ja, bei Type=oneshot startet systemd keine zweite Instanz, solange die erste aktiv ist.
8Uebersprungenen Lauf erkennen?
Ueber den Exit-Code von flock oder eigene Logging-Logik im Skript.
9Lock wird verdaechtig lange gehalten?
Watchdog mit stat auf das Alter der Lock-Datei einrichten, bei Ueberschreitung alarmieren.
10Unabhaengige Jobs mit derselben Lock-Datei?
Haeufiger Fehler. Jeder Job braucht eine eigene, eindeutig benannte Lock-Datei.