J'utiliserais un fichier de verrouillage, puis je configurerais le travail cron pour qu'il s'exécute toutes les minutes. (utilisez crontab -e et * * * * * /path/to/job) De cette façon, vous pouvez simplement continuer à éditer les fichiers et chaque minute ils seront testés. De plus, vous pouvez arrêter le cronjob en touchant simplement le fichier de verrouillage.
#!/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
Après avoir joué avec des éléments de cron qui n'étaient pas instantanément compatibles, j'ai trouvé que l'approche suivante était agréable pour le débogage :
crontab -e
* * * * * /path/to/prog var1 var2 &>>/tmp/cron_debug_log.log
Cela exécutera la tâche une fois par minute et vous pouvez simplement regarder dans le /tmp/cron_debug_log.log
fichier pour comprendre ce qui se passe.
Ce n'est pas exactement le "travail de feu" que vous recherchez, mais cela m'a beaucoup aidé lors du débogage d'un script qui ne fonctionnait pas dans cron au début.
Un tout petit peu au-delà de la portée de votre question... mais voici ce que je fais.
Le "comment tester une tâche cron?" est étroitement liée à "comment tester des scripts qui s'exécutent dans des contextes non interactifs lancés par d'autres programmes ?" Dans cron, le déclencheur est une condition temporelle, mais de nombreuses autres installations *nix lancent des scripts ou des fragments de script de manière non interactive, et souvent les conditions dans lesquelles ces scripts s'exécutent contiennent quelque chose d'inattendu et provoquent des pannes jusqu'à ce que les bogues soient résolus. (Voir aussi :https://stackoverflow.com/a/17805088/237059)
Il est utile d'avoir une approche générale de ce problème.
L'une de mes techniques préférées consiste à utiliser un script que j'ai écrit et qui s'appelle "crontest". Il lance la commande cible dans une session d'écran GNU depuis cron, de sorte que vous pouvez vous connecter avec un terminal séparé pour voir ce qui se passe, interagir avec le script et même utiliser un débogueur.
Pour configurer cela, vous devez utiliser "toutes les étoiles" dans votre entrée crontab et spécifier crontest comme première commande sur la ligne de commande, par exemple :
* * * * * crontest /command/to/be/tested --param1 --param2
Alors maintenant, cron exécutera votre commande toutes les minutes, mais crontest s'assurera qu'une seule instance s'exécute à la fois. Si la commande prend du temps à s'exécuter, vous pouvez faire un "screen -x" pour l'attacher et la regarder s'exécuter. Si la commande est un script, vous pouvez placer une commande "lire" en haut pour l'arrêter et attendre que la pièce jointe de l'écran se termine (appuyez sur Entrée après la pièce jointe)
Si votre commande est un script bash, vous pouvez faire ceci à la place :
* * * * * crontest --bashdb /command/to/be/tested --param1 --param2
Maintenant, si vous vous connectez avec "screen -x", vous serez confronté à une session bashdb interactive, et vous pourrez parcourir le code, examiner les variables, etc.
#!/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
Faites simplement ce que cron fait, exécutez ce qui suit en tant que root
:
run-parts -v /etc/cron.weekly
... ou le suivant si vous recevez l'erreur "Pas un répertoire :-v" :
run-parts /etc/cron.weekly -v
Choix -v
affiche les noms des scripts avant leur exécution.