Warum funktioniert mein Crontab-Skript nicht?

Warum funktioniert mein Crontab-Skript nicht?

ich versuche, ein in meinem Home-Verzeichnis gespeichertes Skript über Crontab auszuführen, aber es funktioniert nicht. Das CRON-Protokoll sagt bei jeder Ausführung nur Folgendes:

Sep  3 18:30:01 backup CRON[6778]: (root) CMD (/home/hannes/script > /tmp/yc.log)
Sep  3 18:30:01 backup CRON[6777]: (CRON) info (No MTA installed, discarding output)

Crontab:

*/1 * * * * /home/hannes/script > /tmp/yc.log

Wenn ich versuche, die Dateierweiterung .sh hinzuzufügen, ändert sich nichts. Die Datei yc.log bleibt leer.

Dies ist das Skript, das ich ausführen möchte (funktioniert einwandfrei, wenn ich es manuell ausführe):

#!/bin/sh
cp -r -p mnt/main-nas/PATH-TO-FILE mnt/backup-nas/01/temp/server
zip -r mnt/backup-nas/01/1.19_Test.`date +%d.%m.%Y_%H.%M.%S`.zip mnt/backup-nas/01/temp/server
rm -r mnt/backup-nas/01/temp/server

Jede Hilfe ist willkommen! :)

Antwort1

Ihr SkriptIstläuft tatsächlich ... aber es tritt irgendwo ein Fehler auf. Und da Sie die Ausgabe nicht erfassen stderr, wird stderr an den Benutzer gesendet, cronder das Skript lokal ausführt. (Und ebenfalls fehlschlägt)

Die Grundursache ist folgende: Ihr Skript leitet nur stdoutzu Dateien weiter. Viele fehlerhafte Skripte und Programme geben jedoch stderrFehlermeldungen aus. Sie müssen dies abfangen, indem Sie 2>&1am Ende Ihrer auszuführenden Befehlszeile Folgendes hinzufügen. cronDadurch werden auch stderrFehler erfasst und in Ihrer Datei protokolliert.

Da Sie es vorher nicht bemerkt haben, wurde stderr per Mail an Sie übermittelt root– aber da Sie keinen lokalen MTA (Mail Transfer Agent, auch bekannt als Local Mail Transport Protocol (LMTP)-Server) für die lokale Übermittlung haben, haben Sie diese Cron-Fehler erhalten. Mit der stderrErfassung sehen Sie jetzt Fehler und erfahren, warum Ihre Skripte nicht richtig ausgeführt wurden.

Sobald Sie die Fehlerausgabe in Ihren Protokollen haben, können Sie Ihr Skript weiter debuggen, um zu ermitteln, was getan werden muss, um die Dinge zu „beheben“.

Antwort2

Es gab also mehrere Probleme. Erstens habe ich vergessen, das 2>&1Ende von hinzuzufügen /home/hannes/script > /tmp/yc.log, damit das Protokoll tatsächlich gespeichert wird. Und zweitens hatte ich einen Tippfehler in meinem Skript, bei dem ich den ersten Schrägstrich in allen Pfaden vergessen habe. Es wurde von diesem home/hannes/...zu diesem /home/hannes/.... Ich hoffe, dies hilft anderen Leuten mit einem ähnlichen Problem und danke an alle, die geantwortet haben :)

Antwort3

Die akzeptierte Antwort ist korrekt und deckt die gestellte Frage ab. Die in der Frage bereitgestellten Informationen weisen jedoch auf ein unabhängiges potenzielles Problem mit diesem Skript hin, vor dem der OP meiner Meinung nach gewarnt werden muss, und eine ordnungsgemäße Erklärung würde für einen Kommentar zu lange dauern. Daher füge ich eine Antwort hinzu, die speziell darauf eingeht.


Abgesehen vom Protokollierungsproblem weist Ihre Anordnung auch einen potenziell unangenehmen Race Condition auf. Da das Skript immer dasselbe Verzeichnis zum Bereitstellen der zu archivierenden Dateien verwendet, wird bei gleichzeitiger Ausführung mehrerer Instanzen des Skripts die erste Ausführung wahrscheinlich Dateien entfernen, an denen nachfolgende Instanzen gerade arbeiten, was zu weiteren Fehlern und höchstwahrscheinlich unvollständigen Archiven führt (da die Dateien verschwinden, bevor zipsie verarbeitet werden können).

Dies kann auf zwei Arten gelöst werden: Entweder sollte das Skript selbst ein Verzeichnis pro Aufruf verwenden oder es sollte eine Dateisperre verwendet werden, um gleichzeitige Ausführungen zu verhindern.

Der erste Ansatz ist viel einfacher. Sie können das Datum einfach dem von Ihnen verwendeten Verzeichnis hinzufügen. Das würde ungefähr so ​​aussehen (beachten Sie, dass dadurch auch sichergestellt wird, dass es datenur einmal aufgerufen wird):

#!/bin/sh
now="$(date +%d.%m.%Y_%H.%M.%S)"
cp -r -p mnt/main-nas/PATH-TO-FILE mnt/backup-nas/01/temp/server/${now}
zip -r mnt/backup-nas/01/1.19_Test.${now}.zip mnt/backup-nas/01/temp/server/${now}
rm -r mnt/backup-nas/01/temp/server/${now}

Der Ansatz mit der Dateisperre ist etwas komplizierter, aber wohl sauberer, da er auch sicherstellt, dass Sie das System nicht versehentlich mit mehreren zipgleichzeitig ausgeführten Befehlen überlasten können. Dazu wird ein Befehl namens flock(Teil des util-linuxPakets unter Ubuntu und Debian, das bereits installiert ist) verwendet und sieht ungefähr so ​​aus (mit Kommentaren, die erklären, was vor sich geht):

#!/bin/sh
# All of this gets run in a subshell so we can hold a file descriptor open
# for all the commands. We're using file descriptor 9 here, but any number
# higher than 2 will work.
(
    # This flock command is what actually takes the lock. The lock itself 
    # persists until the file descriptor is closed when the subshell exits.
    # The -x means it's an exclusive lock (so only one instance can hold it).
    # The -w says to try for that many seconds before failing if something
    # else is holding the lock (this is an important safety net to ensure you
    # don’t get a long queue of these scripts waiting to run).
    # The -n indicates which file descriptor to take the lock on.
    flock -x -w 30 -n 9 || exit 1
    cp -r -p mnt/main-nas/PATH-TO-FILE mnt/backup-nas/01/temp/server
    zip -r mnt/backup-nas/01/1.19_Test.`date +%d.%m.%Y_%H.%M.%S`.zip mnt/backup-nas/01/temp/server
    rm -r mnt/backup-nas/01/temp/server
# And this line closes the subshell, and also sets the path to be used for
# the lock file by opening it as file descriptor 9 for the subshell. /run
# is generally the place you want to put stuff like this, because it will
# get cleaned up automatically every time the system reboots.
) 9> /run/backup-nas.lock

verwandte Informationen