Tes pekerjaan cron mingguan [ditutup]

237

Saya punya #!/bin/bashfile di direktori cron.week.

Apakah ada cara untuk menguji apakah itu berhasil? Tidak bisa menunggu 1 minggu

Saya menggunakan Debian 6 dengan root

dinamis
sumber
4
Tidak bisakah Anda menguji skrip dengan menjalankannya di baris perintah?
Frédéric Hamidi
5
cukup tambahkan entri terpisah di Anda crontabyang menjalankan file Anda setiap beberapa menit, lihat apakah hasil yang diharapkan ada, dan kemudian hapus entri tes dari crontab Anda. cobacrontab -e
davin
61
Tidak, menjalankannya dari baris perintah bukanlah cara yang baik. Hanya menjalankan skrip dari baris perintah tidak menjamin skrip tersebut akan dijalankan seperti halnya pengguna yang sama ketika dijalankan dari cron. Bahkan jika itu dijalankan sebagai pengguna yang sama, Anda tidak akan pernah bisa yakin apakah yang lainnya akan sama. Skrip yang berfungsi dari baris perintah bisa gagal karena segala macam alasan saat dijalankan dari cron.
andynormancx
8
"segala macam" mungkin sedikit hiperbolik ... izin dan variabel lingkungan adalah dua yang muncul dalam pikiran, Anda dapat dengan mudah memiliki kondisi awal lain yang berbeda seperti alias
andynormancx
3
Saya baru saja melalui pengujian pekerjaan cron baru, saya akan menambahkan item lain ke "segala macam". Jika Anda memiliki banyak hal di bash_profile, mereka tidak bisa dijalankan sekali dalam pekerjaan cron, sedangkan pengujian pekerjaan dari baris perintah berfungsi dengan baik. Menguji pekerjaan cron pada baris perintah standar bukanlah tes yang baik sama sekali.
andynormancx

Jawaban:

233

Lakukan saja apa yang dilakukan cron, jalankan yang berikut ini 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 -vmencetak nama skrip sebelum dijalankan.

NNRooth
sumber
4
Jika saya menggunakan opsi -v yang menunjukkan kesalahan "Bukan direktori: -v", tidak ada halaman manual untuk perintah ini di sistem saya, -v berarti verbose kan? Saya menggunakan centos 6.4
maks
3
Untuk menghindari kesalahan "Bukan direktori", saya harus melakukan ini sebagai gantinya: run-parts /etc/cron.weekly -v
Craig Hyatt
22
Tetapi ini tidak memperhitungkan variabel lingkungan yang dapat diatur dalam crontab
fcurella
34
run-partshanya menjalankan skrip dari direktori yang diberikan. Tidak ada hubungannya dengan cron.
Nicolas
23
Ini benar-benar seharusnya tidak dibatalkan dan diterima, selain menjalankan skrip, ia tidak memberi tahu Anda apakah skrip akan benar-benar berfungsi ketika dijalankan dari cron. Gunakan skrip crontest yang sangat baik di salah satu jawaban lain untuk pertanyaan ini.
andynormancx
87

Sedikit di luar cakupan pertanyaan Anda ... tapi inilah yang saya lakukan.

"Bagaimana cara menguji pekerjaan cron?" pertanyaan terkait erat dengan "bagaimana cara menguji skrip yang berjalan dalam konteks non-interaktif yang diluncurkan oleh program lain?" Dalam cron, pemicunya adalah suatu kondisi waktu, tetapi banyak fasilitas * nix lainnya meluncurkan skrip atau skrip skrip dengan cara yang tidak interaktif, dan seringkali kondisi di mana skrip tersebut dijalankan mengandung sesuatu yang tidak terduga dan menyebabkan kerusakan hingga bug diselesaikan. (Lihat juga: https://stackoverflow.com/a/17805088/237059 )

Pendekatan umum untuk masalah ini bermanfaat untuk dimiliki.

Salah satu teknik favorit saya adalah menggunakan skrip yang saya tulis disebut ' crontest '. Ini meluncurkan perintah target di dalam sesi layar GNU dari dalam cron, sehingga Anda dapat melampirkan 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 tentukan 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 "layar -x" untuk melampirkan dan menontonnya berjalan. Jika perintahnya adalah skrip, Anda dapat menempatkan perintah "baca" di bagian atas untuk menghentikannya dan menunggu lampiran layar selesai (tekan enter setelah melampirkan)

Jika perintah Anda adalah skrip bash, Anda bisa melakukannya:

* * * * * crontest --bashdb /command/to/be/tested --param1 --param2

Sekarang, jika Anda lampirkan 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="$@"
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
Stabledog
sumber
2
Luar biasa, solusi sempurna. Semua teknik lain yang saya coba tidak benar-benar berhasil, crontest memecahkan masalah dengan mudah.
andynormancx
1
Ini jauh lebih dari yang saya butuhkan tetapi +1 untuk solusi yang bagus pula; pengaturan cron untuk menjalankan lebih sering dan membuang output ke / tmp cukup baik untuk menemukan masalah saya.
jcollum
2
Keren. Ya, tidak ada alasan untuk menyalakan buldoser jika Anda hanya perlu sekop tangan :)
Stabledog
2
Hal yang bagus. Catatan pada mac saya harus brew tap discoteq/discoteq; brew install flockdan kemudian memodifikasi skrip untuk digunakan/usr/local/bin/flock
Claudiu
1
utilitas yang bagus! Sangat berguna untuk mendiagnosis masalah otentikasi dalam konteks non-interaktif.
Eric Blum
44

Setelah mengacaukan beberapa hal dalam 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 dalam /tmp/cron_debug_log.logfile untuk mencari tahu apa yang sedang terjadi.

Ini bukan "pekerjaan pemadam" yang mungkin Anda cari, tetapi ini banyak membantu saya ketika men-debug skrip yang awalnya tidak bekerja di cron.

Otomatis
sumber
9
Saya akan merekomendasikan pendekatan ini. Masalah dalam kebanyakan kasus adalah Anda tidak melihat kesalahan.
Yauhen Yakimovich
8
Baris salah, tidak ada distribusi yang menggunakan bash untuk cron shell dan karenanya & >> tidak berfungsi Saya sarankan untuk menggunakan >>/tmp/cron_debug_log.log 2>&1Sebaliknya
drizzt
1
Apa yang Anda maksud dengan /path/to/prog- prog mana?
Nathan
3
Program yang akan Anda jalankan dengan cron. Ini bisa berupa usr/home/myFancyScript.shsederhana ls, atau apa pun yang ingin Anda jalankan secara teratur.
Otomatis
Ini berhasil untuk saya. Itu adalah metode termudah untuk melakukan tes cepat untuk memeriksa apakah semuanya baik
abhijit
25

Saya akan menggunakan file kunci dan kemudian mengatur tugas cron untuk dijalankan setiap menit. (gunakan crontab -e dan * * * * * / path / to / job) Dengan begitu Anda bisa terus mengedit file dan setiap menit mereka akan diuji. Selain itu, Anda dapat menghentikan cronjob dengan hanya 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
dave fernholz
sumber
4
Anda juga dapat menggunakan flock(1)dari shell; lihat man 1 flock. Cukup praktis untuk penggunaan seperti itu karena menyediakan pemblokiran otomatis.
Craig Ringer
5

Bagaimana dengan memasukkannya ke dalam cron.hourly, menunggu sampai menjalankan tugas cron per jam berikutnya, lalu menghapusnya? Itu akan berjalan sekali dalam satu jam, dan di lingkungan cron. Anda juga dapat menjalankan ./your_script, tetapi itu tidak akan memiliki lingkungan yang sama seperti di bawah cron.

Jeremiah Willcock
sumber
ini hampir sama dengan jawaban @ Cort3z, dengan kurang detail
jcollum
5

Tidak satu pun dari jawaban ini yang cocok dengan situasi spesifik saya, yaitu saya ingin menjalankan satu pekerjaan cron tertentu, hanya sekali, dan menjalankannya segera.

Saya menggunakan server Ubuntu, dan saya menggunakan cPanel untuk mengatur pekerjaan cron saya.

Saya hanya menuliskan pengaturan saya saat ini, dan kemudian mengeditnya menjadi satu menit dari sekarang. Ketika saya memperbaiki bug lain, saya hanya mengeditnya lagi satu menit dari sekarang. Dan ketika saya sudah selesai, saya hanya mengatur ulang pengaturan kembali seperti semula.

Contoh: Sekarang jam 4:34 sore, jadi saya meletakkan 35 16 * * *, untuk menjalankannya pada 16:35.

Itu bekerja seperti pesona, dan yang paling saya harus menunggu adalah kurang dari satu menit.

Saya pikir ini adalah pilihan yang lebih baik daripada beberapa jawaban lain karena saya tidak ingin menjalankan semua crons mingguan saya, dan saya tidak ingin pekerjaan berjalan setiap menit. Saya perlu beberapa menit untuk memperbaiki apa pun masalahnya sebelum saya siap mengujinya lagi. Semoga ini bisa membantu seseorang.

Ben C
sumber
Mengapa Anda menggunakan cron untuk menjalankan "sekali saja, dan segera jalankan"? Sepertinya Anda akan lebih baik hanya menjalankan skrip secara langsung.
Ian Hunter
4

Selain itu Anda juga dapat menggunakan:

http://pypi.python.org/pypi/cronwrap

untuk membungkus cron Anda untuk mengirimi Anda email setelah berhasil atau gagal.

Low Kian Seong
sumber
10
Bukankah Cron sudah mengirimkan email dan output dari skrip pada saat eksekusi?
Erik
Cron mengirim email kepada pengguna, dan biasanya pengguna untuk sebagian besar pekerjaan cron adalah root atau bukan pengguna layanan interaktif saja, sehingga Anda tidak akan pernah melihat email tersebut. Ini adalah bagaimana server terisi ketika kesalahan memicu banjir besar email dan mereka terpental ke root.
dragon788
3

Solusi yang saya gunakan adalah sebagai berikut:

  1. Edit crontab (gunakan perintah: crontab -e) untuk menjalankan pekerjaan sesering yang diperlukan (setiap 1 menit atau 5 menit)
  2. Ubah skrip shell yang harus dijalankan menggunakan cron untuk mencetak output ke beberapa file (misalnya: echo "Bekerja dengan baik" >>
    output.txt)
  3. Periksa file output.txt menggunakan perintah: tail -f output.txt, yang akan mencetak tambahan terbaru ke dalam file ini, dan dengan demikian Anda dapat melacak eksekusi skrip
Abhilash
sumber
2

Saya biasanya menguji dengan menjalankan pekerjaan yang saya buat seperti ini:

Lebih mudah menggunakan dua terminal untuk melakukan ini.

menjalankan pekerjaan:

#./jobname.sh

pergi ke:

#/var/log and run 

jalankan yang berikut ini:

#tailf /var/log/cron

Ini memungkinkan saya untuk melihat pembaruan log cron secara real time. Anda juga dapat meninjau log setelah Anda menjalankannya, saya lebih suka menonton secara real time.

Berikut adalah contoh pekerjaan cron sederhana. Menjalankan pembaruan yum ...

#!/bin/bash
YUM=/usr/bin/yum
$YUM -y -R 120 -d 0 -e 0 update yum
$YUM -y -R 10 -e 0 -d 0 update

Berikut ini rinciannya:

Perintah pertama akan memperbarui yum sendiri dan selanjutnya akan menerapkan pembaruan sistem.

-R 120: Menetapkan jumlah waktu maksimum yum akan menunggu sebelum melakukan perintah

-e 0: Setel tingkat kesalahan ke 0 (kisaran 0 - 10). 0 berarti hanya mencetak kesalahan kritis yang harus Anda beri tahu.

-d 0: Mengatur level debugging ke 0 - mengubah jumlah hal yang dicetak ke atas atau ke bawah. (kisaran: 0 - 10).

-y: Asumsikan ya; berasumsi bahwa jawaban untuk setiap pertanyaan yang akan ditanyakan adalah ya

Setelah saya membangun pekerjaan cron saya menjalankan perintah di bawah ini untuk membuat pekerjaan saya dapat dieksekusi.

#chmod +x /etc/cron.daily/jobname.sh 

Semoga ini bisa membantu, Dorlack

Dorlack
sumber
2
sudo run-parts --test /var/spool/cron/crontabs/

file dalam crontabs/direktori tersebut harus dapat dieksekusi oleh pemilik - oktal700

Sumber: man crondan NNRooth's

n611x007
sumber
5
Dua nyanyian. Pertama: Untuk menjalankan sesuatu karena sudo menggunakan lingkungan yang berbeda (variabel yang ditentukan). Jadi bug di crontab Anda bisa berfungsi ketika dieksekusi sebagai 'sudo', tetapi tidak akan berfungsi bila dieksekusi sebagai 'root' (dan sebaliknya). Kedua: 'man cron' tidak menunjukkan info ini kepada saya (ok, sepertinya laki-laki saya khusus-debian) ... 'man run-parts' mengatakan bahwa --test tidak menjalankan skrip, tetapi hanya mencetak nama-nama mereka. Jadi skrip bahkan tidak diuji. Satu hal kecil: 'dieksekusi oleh pemilik': Sejauh yang saya tahu, cronjobs hanya dieksekusi sebagai root.
Alex
-1

Saya menggunakan Webmin karena ini adalah permata produktivitas untuk seseorang yang menemukan administrasi baris perintah agak menakutkan dan tidak bisa ditembus.

Ada tombol "Simpan dan Jalankan Sekarang" di antarmuka web "Sistem> Pekerjaan Cron Terjadwal> Edit Pekerjaan Cron".

Ini menampilkan output dari perintah dan persis apa yang saya butuhkan.

Kickaha
sumber