Wie kann ich Cron dazu bringen, jetzt sofort einen Job zum Testen/Debuggen auszuführen? Ohne den Zeitplan zu ändern!

Wie kann ich Cron dazu bringen, jetzt sofort einen Job zum Testen/Debuggen auszuführen? Ohne den Zeitplan zu ändern!

Ich habe einen Cron-Job, der jeden Tag ausgeführt werden soll. Gibt es außer der Änderung des Zeitplans eine andere Möglichkeit, den Befehl jetzt sofort zu testen, um zu sehen, ob er wie vorgesehen funktioniert?

BEARBEITEN: (aus den Kommentaren) Ich weiß, dass der Befehl einwandfrei funktioniert, wenn ich ihn in der Shell (meiner Shell) eingebe, aber ich möchte wissen, ob er richtig funktioniert, wenn er mit Cron ausgeführt wird. Er könnte durch ENV- oder Shell-spezifische Dinge (~ Erweiterung) oder Eigentums- und Berechtigungsdinge oder … beeinflusst werden.

Antwort1

Sie können die Ausführung von Crontab mit dem folgenden Befehl erzwingen:

run-parts /etc/cron.daily

Antwort2

Sie können die Cron-Benutzerumgebung simulieren, wie in„Einen Cron-Job manuell und sofort ausführen“. Auf diese Weise können Sie testen, ob der Job funktioniert, wenn er als Cron-Benutzer ausgeführt wird.


Auszug aus Link:


Schritt 1: Ich habe diese Zeile vorübergehend in die Crontab des Benutzers eingefügt:

* * * * *   /usr/bin/env > /home/username/tmp/cron-env

und habe es dann herausgenommen, nachdem die Datei geschrieben war.

Schritt 2: Ich habe mir ein kleines, als Cron ausführbares Bash-Skript erstellt, das Folgendes enthält:

#!/bin/bash
/usr/bin/env -i $(cat /home/username/tmp/cron-env) "$@"

Als der betroffene Benutzer konnte ich dann

    run-as-cron /the/problematic/script --with arguments --and parameters

Antwort3

Soweit ich weiß, gibt es keine Möglichkeit, das direkt zu tun, da Cron einen speziellen Zweck hat – das Ausführen von Zeitplanbefehlen zu einer bestimmten Zeit. Am besten ist es also, entweder manuell einen (temporären) Crontab-Eintrag zu erstellen oder ein Skript zu schreiben, das die Umgebung entfernt und zurücksetzt.

Erklärung zu „entfernt und setzt die Umgebung zurück“:

Sie könnten ein Wrapper-Skript starten env -i(das die Umgebung entfernt), das eine gespeicherte Umgebung als Quelle verwendet (wobei Sie darauf achten, alle Variablen zu exportieren, möglicherweise indem Sie sie set -azuerst festlegen), bevor Sie Ihr Skript starten.

Die gespeicherte Umgebung wäre die Standardumgebung eines Cron-Jobs, der durch Ausführen als Cron-Job env(oder declare -pje nachdem, welche Shell Ihre Cron-Jobs verwenden) und Speichern seiner Ausgabe aufgezeichnet wird.

Antwort4

Nachdem ich selbst Cron-Jobs debuggen musste, habe ich das folgende Skript geschrieben. Es versucht, vor dem Ausführen eines Befehls genau dieselben Bedingungen wie Cron zu simulieren (das schließt eine geänderte Umgebung ein, hat aber auch mit nicht interaktiven Shells, keinem angeschlossenen Terminal usw. zu tun).

Rufen Sie es mit Ihrem Befehl/Skript als Argument auf, und Sie haben eine sofortige und schmerzlose Möglichkeit, Ihren Cron-Job zu debuggen. Es wird auch auf GitHub gehostet (und möglicherweise aktualisiert):run-as-cron.sh:

#!/bin/bash
# Run as if it was called from cron, that is to say:
#  * with a modified environment
#  * with a specific shell, which may or may not be bash
#  * without an attached input terminal
#  * in a non-interactive shell

function usage(){
    echo "$0 - Run a script or a command as it would be in a cron job," \
                                                       "then display its output"
    echo "Usage:"
    echo "   $0 [command | script]"
}

if [ "$1" == "-h" -o "$1" == "--help" ]; then
    usage
    exit 0
fi

if [ $(whoami) != "root" ]; then
    echo "Only root is supported at the moment"
    exit 1
fi

# This file should contain the cron environment.
cron_env="/root/cron-env"
if [ ! -f "$cron_env" ]; then
    echo "Unable to find $cron_env"
    echo "To generate it, run \"/usr/bin/env > /root/cron-env\" as a cron job"
    exit 0
fi

# It will be a nightmare to expand "$@" inside a shell -c argument.
# Let's rather generate a string where we manually expand-and-quote the arguments
env_string="/usr/bin/env -i "
for envi in $(cat "$cron_env"); do
   env_string="${env_string} $envi "
done

cmd_string=""
for arg in "$@"; do
    cmd_string="${cmd_string} \"${arg}\" "
done

# Which shell should we use?
the_shell=$(grep -E "^SHELL=" /root/cron-env | sed 's/SHELL=//')
echo "Running with $the_shell the following command: $cmd_string"


# Let's redirect the output into files
# and provide /dev/null as input
# (so that the command is executed without an open terminal
# on any standard file descriptor)
so=$(mktemp "/tmp/fakecron.out.XXXX")
se=$(mktemp "/tmp/fakecron.err.XXXX")
"$the_shell" -c "$env_string $cmd_string" > "$so" 2> "$se"  < /dev/null

echo -e "Done. Here is \033[1mstdout\033[0m:"
cat "$so"
echo -e "Done. Here is \033[1mstderr\033[0m:"
cat "$se"
rm "$so" "$se"

verwandte Informationen