Použil bych soubor zámku a pak nastavil úlohu cron tak, aby se spouštěla každou minutu. (použijte crontab -e a * * * * * /cesta/k/úloze) Tímto způsobem můžete pokračovat v úpravách souborů a každou minutu budou otestovány. Navíc můžete cronjob zastavit pouhým dotykem na soubor zámku.
#!/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
Poté, co jsem si pohrával s některými věcmi v cronu, které nebyly okamžitě kompatibilní, jsem zjistil, že následující přístup je vhodný pro ladění:
crontab -e
* * * * * /path/to/prog var1 var2 &>>/tmp/cron_debug_log.log
Tím se úloha spustí jednou za minutu a můžete se jednoduše podívat do /tmp/cron_debug_log.log
soubor, abyste zjistili, co se děje.
Není to zrovna ta "požární práce", kterou byste možná hledali, ale tohle mi hodně pomohlo při ladění skriptu, který v cronu zpočátku nefungoval.
Trochu nad rámec vaší otázky... ale tady je to, co dělám.
Otázka "Jak otestuji úlohu cronu?" otázka je úzce spojena s "jak mohu testovat skripty, které běží v neinteraktivních kontextech spouštěných jinými programy?" V cronu je spouštěčem nějaká časová podmínka, ale spousta dalších *nixových zařízení spouští skripty nebo fragmenty skriptů neinteraktivními způsoby a často podmínky, ve kterých tyto skripty běží, obsahují něco neočekávaného a způsobují poškození, dokud nejsou chyby vyřešeny. (Viz také:https://stackoverflow.com/a/17805088/237059)
Je užitečné mít obecný přístup k tomuto problému.
Jednou z mých oblíbených technik je použití skriptu, který jsem napsal, s názvem 'crontest'. Spouští cílový příkaz v relaci obrazovky GNU z cronu, takže se můžete připojit pomocí samostatného terminálu, abyste viděli, co se děje, pracovat se skriptem nebo dokonce použít debugger.
Chcete-li to nastavit, měli byste v položce crontab použít "all stars" a zadat crontest jako první příkaz na příkazovém řádku, např.:
* * * * * crontest /command/to/be/tested --param1 --param2
Nyní tedy cron spustí váš příkaz každou minutu, ale crontest zajistí, že bude spuštěna vždy pouze jedna instance. Pokud spuštění příkazu nějakou dobu trvá, můžete připojit "screen -x" a sledovat, jak běží. Pokud je příkaz skript, můžete nahoře umístit příkaz „read“, aby se zastavil a počkat na dokončení přílohy obrazovky (po připojení stiskněte Enter)
Pokud je váš příkaz bash skript, můžete místo toho provést toto:
* * * * * crontest --bashdb /command/to/be/tested --param1 --param2
Nyní, pokud se připojíte pomocí "screen -x", budete čelit interaktivní relaci bashdb a můžete procházet kód, zkoumat proměnné atd.
#!/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
Udělejte to, co dělá cron, spusťte následující jako root
:
run-parts -v /etc/cron.weekly
... nebo další, pokud se zobrazí chyba "Není to adresář:-v":
run-parts /etc/cron.weekly -v
Možnost -v
vypíše názvy skriptů před jejich spuštěním.