Un po 'oltre lo scopo della tua domanda ... ma ecco cosa faccio.
Il "come testare un lavoro cron?" domanda è strettamente connessa a "come testare gli script eseguiti in contesti non interattivi lanciati da altri programmi?" In cron, il trigger è una condizione temporale, ma molte altre strutture * nix lanciano script o frammenti di script in modi non interattivi e spesso le condizioni in cui vengono eseguiti quegli script contengono qualcosa di inaspettato e causano la rottura fino a quando i bug non vengono risolti. (Vedi anche: https://stackoverflow.com/a/17805088/237059 )
È utile avere un approccio generale a questo problema.
Una delle mie tecniche preferite è usare una sceneggiatura che ho scritto chiamato " crontest " ". Avvia il comando target all'interno di una sessione dello schermo GNU dall'interno di cron, in modo che tu possa collegarti con un terminale separato per vedere cosa sta succedendo, interagire con lo script, persino usare un debugger.
Per impostarlo, dovresti usare "tutte le stelle" nella voce crontab e specificare crontest come primo comando sulla riga di comando, ad esempio:
* * * * * crontest /command/to/be/tested --param1 --param2
Quindi ora cron eseguirà il tuo comando ogni minuto, ma crontest assicurerà che venga eseguita solo un'istanza alla volta. Se l'esecuzione del comando richiede tempo, è possibile eseguire uno "schermo -x" per collegarlo e vederlo funzionare. Se il comando è uno script, puoi mettere un comando "leggi" in alto per fermarlo e attendere il completamento dell'allegato dello schermo (premi Invio dopo averlo allegato)
Se il tuo comando è uno script bash, puoi invece farlo:
* * * * * crontest --bashdb /command/to/be/tested --param1 --param2
Ora, se ti allego con "screen -x", ti troverai di fronte a una sessione interattiva bashdb e puoi scorrere il codice, esaminare le variabili, ecc.
#!/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="$@"
screenBin=$(which screen 2>/dev/null)
function errExit {
echo "[-err-] $@" | tee -a $crontestLog >&2
}
function log {
echo "[-stat-] $@" >> $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="$@"
return 0
;;
*)
innerArgs="$@"
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 "$@"
log "crontest starting at $(date)"
log "Raw command line: $@"
log "Inner args: $@"
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