Ich habe ein relativ einfaches Bash-Skript, das bei direktem Aufruf hervorragend funktioniert, aber bei der Ausführung per Cron fehlschlägt. Warum schlägt es fehl und wie kann ich es per Cron zum Laufen bringen?
#!/bin/bash
apt-get update -y
apt-get upgrade -y
apt-get install boinc-client -y
Sobald Cron versucht hat, es auszuführen, führt ein manueller Aufruf zu diesem Fehler:
dpkg was interrupted, you must manually run 'sudo dpkg --configure -a' to correct the problem.
Aber solange es beim ersten Mal manuell ausgeführt wird, funktioniert es einwandfrei.
Antwort1
Die übliche Antwort auf diese Art von Fragen ist, dass Cron-Jobs in nicht interaktiven Nicht-Login-Shells ausgeführt werden, sodass die meisten Ihrer Shell-Startdateien (sowohl die systemweiten /etc
als auch Ihre persönlichen Dotfiles in Ihrem Home-Verzeichnis) nicht als Quelle verwendet (eingelesen und ausgeführt) werden, weil die meisten Shell-Startdateien für Login-Shells (die erste Shell, die Sie sehen, wenn Sie sich beim Computer anmelden) oder interaktive Shells (Shells, die mit Terminals, SSH-Sitzungen oder Terminalemulatoren verbunden sind, weil ein Benutzer über das besagte Terminal mit ihnen interagiert) gelten.
Wenn Sie also einen Befehl in einen Cron-Job einfügen, der tatsächlich von einer Umgebungskonfiguration (einschließlich PATH
Änderungen) abhängt, die normalerweise an Orten wie /etc/profile
, /etc/bashrc
, ~/.profile
, oder stattfindet ~/.bashrc
, wird diese Konfiguration für einen Cron-Job nicht durchgeführt. Das Cron-Dateiformat ermöglicht es Ihnen, Umgebungsvariablen für Ihre Jobs anzugeben, daher möchten Sie möglicherweise ein Shell-Startskript zur Quelle angeben BASH_ENV
oder ENV
darauf verweisen. Weitere Informationen finden Sie im Abschnitt „Aufruf“ der bash(1)
Manpage.
Antwort2
Dies ist zwar keine Antwort, aber ich kann dazu keinen Kommentar abgeben. Vorschläge:
Stellen Sie Ihrem Bash-Skript Folgendes voran. Die letzte Zeile, die in der E-Mail-Ausgabe protokolliert wird, ist der fehlgeschlagene Befehl.
set -x set -e
- Stellen Sie sicher, dass Sie Sendmail haben (installieren Sie ein Bereitstellungspaket wie
postfix
oderesmtp
) - Installieren Sie einen Mail-Reader (empfohlen
mutt
) - Stellen Sie sicher, dass die Post Sie erreicht
- über Postfix (wird möglicherweise automatisch vom Installer ausgeführt):
root: my-user-name
hinzufügen/etc/aliases
oder/etc/postfix/aliases
- über cron:
MAILTO="my-user-name"
zur entsprechendencrontab
Datei hinzufügen
- über Postfix (wird möglicherweise automatisch vom Installer ausgeführt):
- Stellen Sie sicher, dass Sie Sendmail haben (installieren Sie ein Bereitstellungspaket wie
Überprüfen Sie, ob das Skript in einer anderen Umgebung ausgeführt werden kann. Geben Sie den vollständigen Pfad zu apt-get an (wahrscheinlich nicht der Übeltäter, da bekannt ist, dass apt-get gefunden wurde) und führen Sie es in einer Konsole (nicht im Terminal) außerhalb von X aus. (Einige Dpkg-Konfigurationsskripte erfordern eine X-Sitzung.)
- Ändern Sie das Skript, um absolute Pfade zu verwenden, d. h.
/usr/bin/apt-get update -y
(ersetzen Sie es durch den richtigen Pfad) - Wechseln Sie zu einer Konsole, indem Sie drücken
ctrl-alt-f1
- Wechseln Sie zum Root-Benutzer:
sudo -i
- Starten Sie eine Shell ohne Anmeldung und ohne Umgebung:
env -i /bin/bash --noprofile --norc
(durch den richtigen Pfad ersetzen) - Führen Sie das Skript aus:
/my/full/path/to/cronscript
. Funktioniert es?
- Ändern Sie das Skript, um absolute Pfade zu verwenden, d. h.
Verfügt das Skript über die entsprechende Berechtigung? Verwenden Sie die System-Crontab? (noch einmal: wahrscheinlich nicht der Übeltäter)
- Sie haben angegeben, dass Sie die System-Crontab verwenden. Überspringen Sie dies also.
Benötigt apt-get Sitzungsunterstützung (Consolekit oder Systemd)? Das ist allerdings nur ein Schuss ins Blaue.
- Ich weiß nicht genug, um helfen zu können.
Antwort3
Ich habe es geschafft, es zu lösen, obwohl ich kaum verstand, was vor sich ging. Es stellte sich heraus, dass die apt-get-Befehle, obwohl ich sie von der Root-Crontab aus ausführte, immer noch ein „sudo“ vor sich brauchten. Logischerweise hatte ich erwartet, dass das nicht nötig sein würde, da das Skript bereits „als Root“ ausgeführt wurde, aber nachdem ich „sudo“ hinzugefügt hatte, funktionierte alles genau wie erwartet.