Saya akan menggunakan file kunci dan kemudian mengatur tugas cron untuk dijalankan setiap menit. (gunakan crontab -e dan * * * * * /path/to/job) Dengan begitu Anda dapat terus mengedit file dan setiap menit mereka akan diuji. Selain itu, Anda dapat menghentikan cronjob hanya dengan menyentuh file kunci.
#!/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
Setelah mengotak-atik beberapa hal di cron yang tidak langsung kompatibel, saya menemukan bahwa pendekatan berikut bagus untuk debugging:
crontab -e
* * * * * /path/to/prog var1 var2 &>>/tmp/cron_debug_log.log
Ini akan menjalankan tugas satu menit sekali dan Anda cukup melihat di /tmp/cron_debug_log.log
file untuk mencari tahu apa yang sedang terjadi.
Ini bukan "pekerjaan api" yang mungkin Anda cari, tetapi ini sangat membantu saya saat men-debug skrip yang awalnya tidak berfungsi di cron.
Sedikit di luar cakupan pertanyaan Anda... tapi inilah yang saya lakukan.
Pertanyaan "bagaimana cara menguji tugas cron?" pertanyaan terkait erat dengan "bagaimana cara menguji skrip yang berjalan dalam konteks non-interaktif yang diluncurkan oleh program lain?" Di cron, pemicunya adalah beberapa kondisi waktu, tetapi banyak fasilitas * nix lainnya meluncurkan skrip atau fragmen skrip dengan cara non-interaktif, dan sering kali kondisi di mana skrip tersebut berjalan mengandung sesuatu yang tidak terduga dan menyebabkan kerusakan hingga bug diselesaikan. (Lihat juga:https://stackoverflow.com/a/17805088/237059 )
Pendekatan umum untuk masalah ini sangat membantu.
Salah satu teknik favorit saya adalah menggunakan skrip yang saya tulis bernama 'crontest'. Ini meluncurkan perintah target di dalam sesi layar GNU dari dalam cron, sehingga Anda dapat memasang dengan terminal terpisah untuk melihat apa yang terjadi, berinteraksi dengan skrip, bahkan menggunakan debugger.
Untuk mengatur ini, Anda akan menggunakan "semua bintang" di entri crontab Anda, dan menentukan crontest sebagai perintah pertama pada baris perintah, misalnya:
* * * * * crontest /command/to/be/tested --param1 --param2
Jadi sekarang cron akan menjalankan perintah Anda setiap menit, tetapi crontest akan memastikan bahwa hanya satu instance yang berjalan pada satu waktu. Jika perintah membutuhkan waktu untuk dijalankan, Anda dapat melakukan "screen -x" untuk melampirkan dan melihatnya berjalan. Jika perintahnya berupa skrip, Anda dapat meletakkan perintah "baca" di bagian atas untuk menghentikannya dan menunggu lampiran layar selesai (tekan enter setelah melampirkan)
Jika perintah Anda adalah skrip bash, Anda dapat melakukannya:
* * * * * crontest --bashdb /command/to/be/tested --param1 --param2
Sekarang, jika Anda melampirkan dengan "screen -x", Anda akan menghadapi sesi bashdb interaktif, dan Anda dapat menelusuri kode, memeriksa variabel, dll.
#!/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
Lakukan saja apa yang dilakukan cron, jalankan yang berikut sebagai root
:
run-parts -v /etc/cron.weekly
... atau yang berikutnya jika Anda menerima kesalahan "Bukan direktori:-v":
run-parts /etc/cron.weekly -v
Opsi -v
mencetak nama skrip sebelum dijalankan.