Ich würde eine Sperrdatei verwenden und dann den Cron-Job so einstellen, dass er jede Minute ausgeführt wird. (verwenden Sie crontab -e und * * * * * /path/to/job) Auf diese Weise können Sie die Dateien einfach weiter bearbeiten und jede Minute werden sie getestet. Außerdem können Sie den Cronjob stoppen, indem Sie einfach auf die Sperrdatei tippen.
#!/bin/sh
if [ -e /tmp/cronlock ]
then
echo "cronjob locked"
exit 1
fi
touch /tmp/cronlock
<...do your regular cron here ....>
rm -f /tmp/cronlock
Nachdem ich mit einigen Dingen in cron herumgespielt hatte, die nicht sofort kompatibel waren, fand ich, dass der folgende Ansatz gut zum Debuggen war:
crontab -e
* * * * * /path/to/prog var1 var2 &>>/tmp/cron_debug_log.log
Dadurch wird die Aufgabe einmal pro Minute ausgeführt und Sie können einfach in /tmp/cron_debug_log.log
nachsehen Datei, um herauszufinden, was los ist.
Es ist nicht gerade der "Fire-Job", nach dem Sie vielleicht suchen, aber das hat mir sehr geholfen, als ich ein Skript debuggte, das anfangs nicht in Cron funktionierte.
Geht etwas über den Rahmen Ihrer Frage hinaus... aber ich mache Folgendes.
Die Frage "Wie teste ich einen Cron-Job?" Die Frage ist eng verbunden mit "Wie teste ich Skripte, die in nicht interaktiven Kontexten ausgeführt werden, die von anderen Programmen gestartet werden?" In cron ist der Auslöser eine Zeitbedingung, aber viele andere *nix-Funktionen starten Skripte oder Skriptfragmente auf nicht interaktive Weise, und oft enthalten die Bedingungen, unter denen diese Skripte ausgeführt werden, etwas Unerwartetes und verursachen einen Bruch, bis die Fehler behoben sind. (Siehe auch:https://stackoverflow.com/a/17805088/237059 )
Eine allgemeine Herangehensweise an dieses Problem ist hilfreich.
Eine meiner Lieblingstechniken ist die Verwendung eines von mir geschriebenen Skripts mit dem Namen „crontest“. Es startet den Zielbefehl innerhalb einer GNU-Bildschirmsitzung aus cron heraus, sodass Sie mit einem separaten Terminal anhängen können, um zu sehen, was los ist, mit dem Skript interagieren und sogar einen Debugger verwenden können.
Um dies einzurichten, würden Sie "alle Sterne" in Ihrem crontab-Eintrag verwenden und crontest als ersten Befehl in der Befehlszeile angeben, z. B.:
* * * * * crontest /command/to/be/tested --param1 --param2
Cron führt Ihren Befehl jetzt jede Minute aus, aber Crontest stellt sicher, dass jeweils nur eine Instanz ausgeführt wird. Wenn die Ausführung des Befehls einige Zeit in Anspruch nimmt, können Sie ein "screen -x" ausführen, um ihn anzuhängen und zu beobachten, wie er ausgeführt wird. Wenn es sich bei dem Befehl um ein Skript handelt, können Sie oben einen "Lesen"-Befehl einfügen, damit er stoppt, und warten, bis der Bildschirmanhang abgeschlossen ist (drücken Sie nach dem Anhängen die Eingabetaste)
Wenn Ihr Befehl ein Bash-Skript ist, können Sie stattdessen Folgendes tun:
* * * * * crontest --bashdb /command/to/be/tested --param1 --param2
Wenn Sie jetzt mit "screen -x" anhängen, sehen Sie sich einer interaktiven Bashdb-Sitzung gegenüber, und Sie können den Code schrittweise durchgehen, Variablen untersuchen usw.
#!/bin/bash
# crontest
# See https://github.com/Stabledog/crontest for canonical source.
# Test wrapper for cron tasks. The suggested use is:
#
# 1. When adding your cron job, use all 5 stars to make it run every minute
# 2. Wrap the command in crontest
#
#
# Example:
#
# $ crontab -e
# * * * * * /usr/local/bin/crontest $HOME/bin/my-new-script --myparams
#
# Now, cron will run your job every minute, but crontest will only allow one
# instance to run at a time.
#
# crontest always wraps the command in "screen -d -m" if possible, so you can
# use "screen -x" to attach and interact with the job.
#
# If --bashdb is used, the command line will be passed to bashdb. Thus you
# can attach with "screen -x" and debug the remaining command in context.
#
# NOTES:
# - crontest can be used in other contexts, it doesn't have to be a cron job.
# Any place where commands are invoked without an interactive terminal and
# may need to be debugged.
#
# - crontest writes its own stuff to /tmp/crontest.log
#
# - If GNU screen isn't available, neither is --bashdb
#
crontestLog=/tmp/crontest.log
lockfile=$(if [[ -d /var/lock ]]; then echo /var/lock/crontest.lock; else echo /tmp/crontest.lock; fi )
useBashdb=false
useScreen=$( if which screen &>/dev/null; then echo true; else echo false; fi )
innerArgs="[email protected]"
screenBin=$(which screen 2>/dev/null)
function errExit {
echo "[-err-] [email protected]" | tee -a $crontestLog >&2
}
function log {
echo "[-stat-] [email protected]" >> $crontestLog
}
function parseArgs {
while [[ ! -z $1 ]]; do
case $1 in
--bashdb)
if ! $useScreen; then
errExit "--bashdb invalid in crontest because GNU screen not installed"
fi
if ! which bashdb &>/dev/null; then
errExit "--bashdb invalid in crontest: no bashdb on the PATH"
fi
useBashdb=true
;;
--)
shift
innerArgs="[email protected]"
return 0
;;
*)
innerArgs="[email protected]"
return 0
;;
esac
shift
done
}
if [[ -z $sourceMe ]]; then
# Lock the lockfile (no, we do not wish to follow the standard
# advice of wrapping this in a subshell!)
exec 9>$lockfile
flock -n 9 || exit 1
# Zap any old log data:
[[ -f $crontestLog ]] && rm -f $crontestLog
parseArgs "[email protected]"
log "crontest starting at $(date)"
log "Raw command line: [email protected]"
log "Inner args: [email protected]"
log "screenBin: $screenBin"
log "useBashdb: $( if $useBashdb; then echo YES; else echo no; fi )"
log "useScreen: $( if $useScreen; then echo YES; else echo no; fi )"
# Were building a command line.
cmdline=""
# If screen is available, put the task inside a pseudo-terminal
# owned by screen. That allows the developer to do a "screen -x" to
# interact with the running command:
if $useScreen; then
cmdline="$screenBin -D -m "
fi
# If bashdb is installed and --bashdb is specified on the command line,
# pass the command to bashdb. This allows the developer to do a "screen -x" to
# interactively debug a bash shell script:
if $useBashdb; then
cmdline="$cmdline $(which bashdb) "
fi
# Finally, append the target command and params:
cmdline="$cmdline $innerArgs"
log "cmdline: $cmdline"
# And run the whole schlock:
$cmdline
res=$?
log "Command result: $res"
echo "[-result-] $(if [[ $res -eq 0 ]]; then echo ok; else echo fail; fi)" >> $crontestLog
# Release the lock:
9<&-
fi
Tun Sie einfach, was Cron tut, führen Sie Folgendes als root
aus :
run-parts -v /etc/cron.weekly
... oder das nächste, wenn Sie den Fehler "Kein Verzeichnis:-v" erhalten:
run-parts /etc/cron.weekly -v
Option -v
gibt die Skriptnamen aus, bevor sie ausgeführt werden.