Vom rechten Pfad abgekommen
Wegen einer Race Condition auf einem meiner Systeme kommen einige Netzwerkinterfaces nicht up wenn das System neustartet.
Da das System relativ kritisch ist (arbeitet als Ethernet-Switch) muss es auch nach einem Stromausfall automatisch wieder sauber starten. Aus diesem Grund habe ich einen Cron-Job installiert der ein Script ausführt was im Prinzip einfach nur ifconfig [Interface] up aufruft mit einer Verzögerung nach dem booten des Systems.
@reboot root sleep 20;/home/pi/bring_up.sh
Leider änderte der Job an der Situation nichts, egal wie hoch ich die Verzögerung konfigurierte, führte ich den Befehl manuell aus funktionierte alles wie gewünscht
Daher ging ich davon aus das cron den Job gar nicht ausführt, also baute ich in den Befehl das ein zufälliger Wert in eine Datei geschrieben werden sollte und das passierte tatsächlich auch - nach dem start war eine entsprechende Datei angelegt und der Wert dort hineingeschrieben.
@reboot root sleep 20;/home/pi/bring_up.sh; echo "whatever" > /tmp/whatever
Nur der eigentliche Befehl erfolgte immer noch nicht, also habe ich stderr (der Stream unter Linux der die Fehlerausgaben enthält) ebenfalls in eine Datei umgeleitet:
@reboot root sleep 20;/home/pi/bring_up.sh 2> /tmp/error
Und siehe da:
command not found: ifconfig
Aha, er findet ifconfig nicht… er findet ifconfig nicht??
Unter Linux definiert in der Shell die Variable PATH wo nach Befehlen gesucht wird. Das was man in der interaktiven Shell als PATH hat stimmt nicht zwangsläufig damit überein was cron als PATH sieht.
Lösen lässt das sich u.a. so:
PATH="/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/local/games:/snap/bin:/opt/bin"
@reboot root sleep 20;/home/pi/bring_up.sh 2> /tmp/error
|
🪛
|
Variable-Expansion (oder ähnliche Shell-Ausdrücke) funktionieren in cron nicht. PATH="${PATH}:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/local/games:/snap/bin:/opt/bin"
würde "${PATH}" nicht in den Inhalt von PATH auflösen. |
Hintergrund
Cron führt führt alle Kommandos in einer Posix-Shell aus - aka. sh - also nicht bash, dash oder einer anderen Shell die man normalerweise als Benutzer ausführen würde.
Darüber hinaus wird die Shell nicht als Interaktiv oder Login-Shell ausgeführt.
Das heißt "übliche" Dateien wie .bashrc und .profile werden nicht geladen und ggf. dort definierte Erweiterungen von PATH nicht gesetzt.
Man kann u.a. /etc/environment nutzen, diese gilt für alle Shells und alle Benutzer.
Natürlich kann man die PATH-Variable auch in einem Script setzen wenn man ein solches in cron aufruft (wie in meinem Fall).
Des weiteren gibt die Möglichkeit vor dem ausführen des eigentlichen Befehls in eine interaktive Shell oder Login-Shell oder Beides zu wechseln: https://www.baeldung.com/linux/load-env-variables-in-cron-job