Abstrakt
Der richtige Code sollte sein:
#!/bin/sh
[ "$#" -eq 0 ] && echo "Usage: $0 command [args]" && exit 1
[ "$(date -d tomorrow +'%d')" = 01 ] || exit 0
exec "$@"
Rufen Sie dieses Skript auf end_of_month.sh
und der Aufruf in cron lautet einfach:
00 12 28-31 * * /path/to/script/end_of_month.sh command
Dadurch wird das Skript end_of_month
(das intern überprüft, ob der Tag der letzte Tag des Monats ist) nur an den Tagen 28, 29, 30 und 31 ausgeführt. An keinem anderen Tag muss das Monatsende überprüft werden.
Alter Beitrag.
Dies ist ein Zitat aus dem Buch "Linux Command Line and Shell Scripting Bible" von Richard Blum, Christine Bresnahan, S. 442, 3. Auflage, John Wiley & Sons © 2015.
Ja, das steht darin, aber das ist falsch / unvollständig:
- Fehlender Abschluss
fi
.
- Benötigt Platz zwischen
[
und den folgenden `
.
- Es wird dringend empfohlen, anstelle von $ (…) zu verwenden
`…`
.
- Es ist wichtig, dass Sie Anführungszeichen für Erweiterungen wie verwenden
"$(…)"
- Es gibt ein zusätzliches
;
Nachthen
Wie soll ich wissen? ( naja , aus Erfahrung ☺) aber Sie können Shellcheck ausprobieren . Fügen Sie den Code aus dem Buch ein (nach den Sternchen) und es werden Ihnen die oben aufgeführten Fehler sowie ein "fehlender Schebang" angezeigt. Ein Skript ohne Fehler in Shellcheck lautet wie folgt:
#!/bin/sh
if [ "$(date +%d -d tomorrow)" = 01 ] ; then script.sh; fi
Diese Seite funktioniert, weil das, was geschrieben wurde, "Shell-Code" ist. Das ist eine Syntax, die in vielen Shells funktioniert.
Einige Probleme, die Shellcheck nicht erwähnt, sind:
Es wird davon ausgegangen, dass der Datumsbefehl die GNU-Datumsversion ist. Die mit einer -d
Option, die tomorrow
als Wert akzeptiert wird (Busybox hat die Option -d, versteht sie aber morgen nicht und BSD hat eine -d
Option, bezieht sich jedoch nicht auf die "Anzeige" der Zeit).
Es ist besser, das Format nach allen Optionen festzulegen date -d tomorrow +'%d'
.
Die Cron-Startzeit ist immer in der Ortszeit. Dies kann dazu führen, dass ein Job 1 Stunde früher als eine genaue Tageszählung startet, wenn die Sommerzeit eingestellt oder deaktiviert wurde.
Was wir gemacht haben, ist ein Shell-Skript, das mit cron aufgerufen werden könnte. Wir können das Skript weiter modifizieren, um Argumente des auszuführenden Programms oder Befehls wie folgt zu akzeptieren (schließlich den richtigen Code):
#!/bin/sh
[ "$#" -eq 0 ] && echo "Usage: $0 command [args]" && exit 1
[ "$(date -d tomorrow +'%d')" = 01 ] || exit 0
exec "$@"
Rufen Sie dieses Skript auf end_of_month.sh
und der Aufruf in cron lautet einfach:
00 12 28-31 * * /path/to/script/end_of_month.sh command
Dadurch wird das Skript end_of_month
(das intern überprüft, ob der Tag der letzte Tag des Monats ist) nur an den Tagen 28, 29, 30 und 31 ausgeführt. An keinem anderen Tag muss das Monatsende überprüft werden.
Stellen Sie sicher, dass der richtige Pfad enthalten ist. Der Pfad in cron ist (wahrscheinlich) nicht derselbe wie der Benutzerpfad.
Beachten Sie, dass ein Skript zum Monatsende getestet wurde (wie unten angegeben), das viele andere Dienstprogramme oder Skripte aufrufen kann.
Dadurch wird auch das zusätzliche Problem vermieden, das cron mit der vollständigen Befehlszeile generiert:
- Cron teilt die Befehlszeile auf jede auf,
%
auch wenn sie entweder mit '
oder angegeben ist "
( \
hier funktioniert nur a ). Dies ist eine übliche Methode, mit der Cron-Jobs fehlschlagen.
Sie können testen, ob das end_of_month.sh
Skript an einem bestimmten Datum ordnungsgemäß funktioniert (ohne bis zum Ende des Monats zu warten, um festzustellen, dass es nicht funktioniert), indem Sie es mit faketime testen:
$ faketime 2018/10/31 ./end_of_month echo "Command will be executed...."
Command will be executed....