Apa yang salah dengan dua pekerjaan cron ini?

13

Saya memiliki tugas cron berikut yang ditentukan.

55  8   *   *   3   /usr/bin/php /home/mark/dev/processes/customClient/events.php > /home/mark/dev/processes/customClient/events-`date +%Y-%m-%d --date='last Wednesday'`-`date +%Y-%m-%d`.csv
0   9   *   *   3   /usr/bin/echo 'The csv for last week, trying my hand at automatiging this' | /usr/bin/mutt <emailaddress> -s 'Events from `date +%Y-%m-%d --date='last Wednesday'`-`date +%Y-%m-%d`' -a '/home/mark/dev/processes/customClient/events-`date +%Y-%m-%d --date='last Wednesday'`-`date +%Y-%m-%d`.csv'

Tampaknya berfungsi dengan baik jika saya menjalankannya perintah di atas langsung dari baris perintah. Tetapi ketika saya memeriksa jalannya script pagi ini saya mendapat e-mail yang menyatakan (saya parafrase karena saya tidak sengaja menghapusnya) bahwa kutu belakang tidak ditutup dengan benar.

Markus D
sumber
FYI Saya hanya menguji ulang pekerjaan cron dan mendapatkan kesalahan berikut. /bin/sh: 1: Syntax error: EOF in backquote substitution Untuk pekerjaan cron pertama. /bin/sh: 1: Syntax error: Unterminated quoted string Untuk pekerjaan cron kedua.
Mark D
2
Backticks sudah usang karena alasan ini; mengubah ke $(...)akan membantu Anda menangani masalah mengutip ...
jasonwryan
1
Anda pasti ingin memeriksa pertanyaan saya. Ini memiliki jawaban oleh Stephane Chazelas yang menjelaskan bagaimana Anda dapat membuat shell interaktif yang identik dengan lingkungan yang akan dilihat oleh tugas cron Anda. Jika Anda berjalan melalui prosedur kecilnya, Anda mendapatkan prompt dan Anda dapat menguji cronjob langkah demi langkah dan melihat di mana itu gagal. unix.stackexchange.com/a/56503/16841 Tentu itu bukan 100% cocok untuk pertanyaan Anda, tetapi dapat membantu Anda memecahkan masalah crontab.
jippie

Jawaban:

14

Saya sangat menyarankan menempatkan pekerjaan cron non-sepele ke file skrip shell mereka sendiri, karena berbagai alasan:

  • Lebih mudah untuk di-debug: Anda hanya dapat menjalankan skrip alih-alih menyalin menempelkan garis panjang, dan dengan garis shebang kanan, ia berperilaku jauh lebih dapat diprediksi daripada jika Anda memiliki perintah yang sama langsung di crontab
  • Lebih mudah dibaca: tidak perlu membuatnya 200+ karakter satu-liner, Anda dapat memformatnya dengan baik sehingga mudah dibaca dan dipahami untuk semua orang
  • Tambahkan skrip ke kontrol versi
janos
sumber
8
Dan menempatkan %karakter yang merepotkan dalam skrip akan mencegah crondari mengubahnya menjadi baris baru, yang merupakan masalah Anda yang sebenarnya.
Ian D. Allen
Saya tidak setuju. Anda cenderung lupa skrip mana yang melakukan apa. Saya berbicara dari pengalaman.
Sridhar Sarnobat
30

Ada tiga penyebab umum untuk perintah pekerjaan cron untuk berperilaku berbeda dibandingkan dengan perintah yang diketik langsung ke shell interaktif, dalam urutan umum kesamaan:

  • Cron menyediakan lingkungan terbatas, mis. Minimal $PATH, dan variabel-variabel lain yang diharapkan hilang.
  • Cron memanggil /bin/shsecara default, sedangkan Anda mungkin menggunakan beberapa shell lain secara interaktif.
  • Cron memperlakukan %karakter secara khusus (itu diubah menjadi baris baru dalam perintah).
  • Cron tidak menyediakan lingkungan terminal atau grafis.

Anda harus mendahului semua %karakter dengan \file crontab, yang memberitahu cron untuk hanya menempatkan persen dalam perintah. Ingatlah bahwa ketika Anda menggunakan dateperintah dalam pekerjaan cron.

55  8   *   *   3   /usr/bin/php /home/mark/dev/processes/customClient/events.php > "/home/mark/dev/processes/customClient/events-$(date +\%Y-\%m-\%d --date='last Wednesday')-$(date +\%Y-\%m-\%d).csv"
0   9   *   *   3   /usr/bin/echo 'The csv for last week, trying my hand at automatiging this' | /usr/bin/mutt <emailaddress> -s "Events from $(date +\%Y-\%m-\%d --date='last Wednesday')-$(date +\%Y-\%m-\%d)" -a "/home/mark/dev/processes/customClient/events-$(date +\%Y-\%m-\%d --date='last Wednesday')-$(date +\%Y-\%m-\%d).csv"

Saya juga memperbaiki beberapa masalah penawaran:

  • Ini tidak menyebabkan Anda masalah selain dengan keterbacaan, tetapi Anda tidak boleh menggunakan backtick untuk substitusi perintah. Gunakan $(…)sebaliknya: aturan parsingnya lebih sederhana.
  • Selalu gunakan tanda kutip ganda di sekitar penggantian variabel dan perintah: "$somevariable", "$(somecommand)". Di sini, kurangnya tanda kutip tidak berbahaya karena dateperintah tidak pernah mengembalikan karakter khusus untuk format yang Anda gunakan, tetapi Anda harus hati-hati mengingat karakter mana yang spesial dan periksa ini setiap kali Anda meninggalkan subtitusi yang tidak dikutip. Tetap sederhana, selalu gunakan tanda kutip ganda kecuali jika Anda ingin pemisahan bidang dan pembuatan nama file terjadi pada hasilnya.
  • Anda memiliki beberapa kutipan tunggal yang mencegah ekspansi di sekitar beberapa penggantian perintah. Gunakan tanda kutip ganda sebagai gantinya.
Gilles 'SANGAT berhenti menjadi jahat'
sumber
0

Anda tampaknya telah bersarang 'dalam muttperintah:

'Acara dari date +%Y-%m-%d --date='last Wednesday'- date +%Y-%m-%d'

Coba gunakan "bukan bagian dalam 'sehingga pernyataan itu dibaca

'Acara dari date +%Y-%m-%d --date="last Wednesday"- date +%Y-%m-%d'

Marko Kudjerski
sumber
Saya tidak yakin itulah masalahnya. Tapi setelah mencobanya di kedua tugas cron eksekusi tidak berhasil.
Mark D