GNU/Linux >> Belajar Linux >  >> Linux

Mengapa crontab saya tidak berfungsi, dan bagaimana cara mengatasinya?

Solusi 1:

Cara memperbaiki semua kesengsaraan/masalah terkait crontab Anda (Linux)

Ini adalah wiki komunitas, jika Anda melihat sesuatu yang salah dengan jawaban ini atau memiliki informasi tambahan, silakan edit.

Pertama, terminologi dasar:

  • cron(8) adalah daemon yang menjalankan perintah terjadwal.
  • crontab(1) adalah program yang digunakan untuk memodifikasi file crontab(5) pengguna.
  • crontab(5) adalah file per pengguna yang berisi instruksi untuk cron(8).

Berikutnya, edukasi tentang cron:

Setiap pengguna di sistem mungkin memiliki file crontab mereka sendiri. Lokasi file root dan crontab pengguna bergantung pada sistem tetapi umumnya di bawah /var/spool/cron .

Ada /etc/crontab di seluruh sistem file, /etc/cron.d direktori mungkin berisi fragmen crontab yang juga dibaca dan ditindaklanjuti oleh cron. Beberapa distribusi Linux (misalnya, Red Hat) juga memiliki /etc/cron.{hourly,daily,weekly,monthly} yang merupakan direktori, skrip di dalamnya yang akan dieksekusi setiap jam/hari/minggu/bulan, dengan hak akses root.

root selalu dapat menggunakan perintah crontab; pengguna biasa mungkin atau mungkin tidak diberikan akses. Saat Anda mengedit file crontab dengan perintah crontab -e dan simpan, crond memeriksanya untuk validitas dasar tetapi tidak menjamin file crontab Anda terbentuk dengan benar. Ada file bernama cron.deny yang akan menentukan pengguna mana yang tidak dapat menggunakan cron. cron.deny lokasi file bergantung pada sistem dan dapat dihapus yang memungkinkan semua pengguna menggunakan cron.

Jika komputer tidak dihidupkan atau daemon crond tidak berjalan, dan tanggal/waktu untuk menjalankan perintah telah berlalu, crond tidak akan mengejar dan menjalankan kueri sebelumnya.

rincian crontab, cara merumuskan perintah:

Perintah crontab diwakili oleh satu baris. Anda tidak dapat menggunakan \ untuk memperluas perintah melalui beberapa baris. Hash (# ) tanda mewakili komentar yang berarti apa pun di baris itu diabaikan oleh cron. Spasi kosong dan baris kosong di awal diabaikan.

Berhati-hatilah saat menggunakan persen (% ) masuk perintah Anda. Kecuali mereka lolos \% mereka diubah menjadi baris baru dan semuanya setelah % pertama yang tidak lolos diteruskan ke perintah Anda di stdin.

Ada dua format untuk file crontab:

  • Crontab pengguna

     # Example of job definition:
     # .---------------- minute (0 - 59)
     # |  .------------- hour (0 - 23)
     # |  |  .---------- day of month (1 - 31)
     # |  |  |  .------- month (1 - 12) OR jan,feb,mar,apr ...
     # |  |  |  |  .---- day of week (0 - 6) (Sunday=0 or 7)
     # |  |  |  |  |
     # *  *  *  *  *   command to be executed
    
  • Lebar sistem /etc/crontab dan /etc/cron.d fragmen

     # Example of job definition:
     # .---------------- minute (0 - 59)
     # |  .------------- hour (0 - 23)
     # |  |  .---------- day of month (1 - 31)
     # |  |  |  .------- month (1 - 12) OR jan,feb,mar,apr ...
     # |  |  |  |  .---- day of week (0 - 6) (Sunday=0 or 7)
     # |  |  |  |  |
     # *  *  *  *  * user-name  command to be executed
    

Perhatikan bahwa yang terakhir membutuhkan nama pengguna. Perintah akan dijalankan sebagai pengguna bernama.

5 bidang pertama baris menunjukkan waktu saat perintah harus dijalankan. Anda dapat menggunakan angka atau nama hari/bulan jika berlaku dalam spesifikasi waktu.

  • Bidang dipisahkan oleh spasi atau tab.
  • Koma (, ) digunakan untuk menentukan daftar misalnya 1,4,6,8 yang artinya dijalankan pada 1,4,6,8.
  • Rentang ditentukan dengan tanda hubung (- ) dan dapat digabungkan dengan daftar mis. 1-3,9-12 yang berarti antara 1 dan 3 kemudian antara 9 dan 12.
  • / karakter dapat digunakan untuk memperkenalkan langkah mis. 2/5 yang artinya mulai dari 2 lalu setiap 5 (2,7,12,17,22...). Mereka tidak membungkus melewati akhir.
  • Sebuah tanda bintang (* ) dalam suatu bidang menandakan seluruh rentang untuk bidang itu (mis. 0-59 untuk bidang menit).
  • Rentang dan langkah dapat digabungkan, mis. */2 menandakan mulai dari minimum untuk bidang yang relevan lalu setiap 2 mis. 0 untuk menit (0,2...58), 1 untuk bulan (1,3 ... 11) dll.

Men-debug perintah cron

Periksa email!

Secara default cron akan mengirimkan output apa pun dari perintah ke pengguna yang menjalankan perintah tersebut. Jika tidak ada keluaran, tidak akan ada surat. Jika Anda ingin cron mengirim email ke akun lain maka Anda dapat mengatur variabel lingkungan MAILTO di file crontab mis.

[email protected]
1 2 * * * /path/to/your/command

Rekam hasilnya sendiri

Anda dapat mengarahkan stdout dan stderr ke file. Sintaks yang tepat untuk menangkap output dapat bervariasi tergantung pada apa yang digunakan shell cron. Berikut adalah dua contoh yang menyimpan semua output ke file di /tmp/mycommand.log :

1 2 * * * /path/to/your/command &>/tmp/mycommand.log
1 2 * * * /path/to/your/command >/tmp/mycommand.log 2>&1

Lihat log

Cron mencatat tindakannya melalui syslog, yang (tergantung pada pengaturan Anda) sering masuk ke /var/log/cron atau /var/log/syslog .

Jika perlu, Anda dapat memfilter pernyataan cron dengan mis.

grep CRON /var/log/syslog 

Sekarang setelah kita membahas dasar-dasar cron, di mana letak file dan cara menggunakannya, mari kita lihat beberapa masalah umum.

Periksa apakah cron berjalan

Jika cron tidak berjalan maka perintah Anda tidak akan dijadwalkan ...

ps -ef | grep cron | grep -v grep

harus memberi Anda sesuatu seperti

root    1224   1  0 Nov16 ?    00:00:03 cron

atau

root    2018   1  0 Nov14 ?    00:00:06 crond

Jika tidak, mulai ulang

/sbin/service cron start

atau

/sbin/service crond start

Mungkin ada metode lain; gunakan apa yang disediakan distro Anda.

cron menjalankan perintah Anda di lingkungan terbatas.

Variabel lingkungan apa yang tersedia kemungkinan sangat terbatas. Biasanya, Anda hanya akan menentukan beberapa variabel, seperti $LOGNAME , $HOME , dan $PATH .

Catatan khusus adalah PATH dibatasi untuk /bin:/usr/bin . Sebagian besar masalah "skrip cron saya tidak berfungsi" disebabkan oleh jalur terbatas ini . Jika perintah Anda berada di lokasi yang berbeda, Anda dapat menyelesaikannya dengan beberapa cara:

  1. Berikan path lengkap ke perintah Anda.

     1 2 * * * /path/to/your/command
    
  2. Berikan PATH yang sesuai di file crontab

     PATH=/bin:/usr/bin:/path/to/something/else
     1 2 * * * command 
    

Jika perintah Anda memerlukan variabel lingkungan lain, Anda juga dapat menentukannya di file crontab.

cron menjalankan perintah Anda dengan cwd ==$HOME

Di mana pun program yang Anda jalankan berada di sistem file, direktori kerja saat ini dari program saat cron dijalankan akan menjadi direktori home pengguna . Jika Anda mengakses file dalam program Anda, Anda harus mempertimbangkan hal ini jika Anda menggunakan jalur relatif, atau (sebaiknya) hanya menggunakan jalur yang sepenuhnya memenuhi syarat di mana saja, dan menyelamatkan semua orang dari banyak kebingungan.

Perintah terakhir di crontab saya tidak berjalan

Cron umumnya mengharuskan perintah diakhiri dengan baris baru. Edit crontab Anda; pergi ke akhir baris yang berisi perintah terakhir dan sisipkan baris baru (tekan enter).

Periksa format crontab

Anda tidak dapat menggunakan crontab yang diformat crontab pengguna untuk /etc/crontab atau fragmen di /etc/cron.d dan sebaliknya. Crontab yang diformat pengguna tidak menyertakan nama pengguna di posisi ke-6 berturut-turut, sedangkan crontab yang diformat sistem menyertakan nama pengguna dan menjalankan perintah sebagai pengguna tersebut.

Saya meletakkan file di /etc/cron.{hourly,daily,weekly,monthly} dan tidak berjalan

  • Periksa apakah nama file tidak memiliki ekstensi lihat run-parts
  • Pastikan file memiliki izin eksekusi.
  • Beri tahu sistem apa yang harus digunakan saat menjalankan skrip Anda (misalnya, masukkan #!/bin/sh di atas)

Bug terkait tanggal Cron

Jika tanggal Anda baru-baru ini diubah oleh pengguna atau pembaruan sistem, zona waktu atau lainnya, maka crontab akan mulai berperilaku tidak menentu dan menunjukkan bug aneh, terkadang berfungsi, terkadang tidak. Ini adalah upaya crontab untuk mencoba "melakukan apa yang Anda inginkan" ketika waktu berubah dari bawahnya. Bidang "menit" akan menjadi tidak efektif setelah jam diubah. Dalam skenario ini, hanya tanda bintang yang akan diterima. Mulai ulang cron dan coba lagi tanpa terhubung ke internet (sehingga tanggal tidak memiliki kesempatan untuk mengatur ulang ke salah satu server waktu).

Tanda persen, sekali lagi

Untuk menekankan saran tentang tanda persen, berikut adalah contoh apa yang dilakukan cron dengan mereka:

# cron entry
* * * * * cat >$HOME/cron.out%foo%bar%baz

akan membuat file ~/cron.out yang berisi 3 baris

foo
bar
baz

Ini sangat mengganggu saat menggunakan date memerintah. Pastikan untuk menghindari tanda persen

* * * * * /path/to/command --day "$(date "+\%Y\%m\%d")"

Waspadalah terhadap Sudo

saat dijalankan sebagai pengguna non-root,

crontab -e

akan membuka crontab pengguna, sedangkan

sudo crontab -e

akan membuka crontab pengguna root. Tidak disarankan untuk menjalankan perintah sudo di tugas cron, jadi jika Anda mencoba menjalankan perintah sudo di cron pengguna, coba pindahkan perintah tersebut ke cron root dan hapus sudo dari perintah.

Solusi 2:

Debian Linux dan turunannya (Ubuntu, Mint, dll) memiliki beberapa keanehan yang dapat mencegah pekerjaan cron Anda dijalankan; khususnya, file di /etc/cron.d , /etc/cron.{hourly,daily,weekly,monthly} harus :

  • dimiliki oleh root
  • hanya dapat ditulis oleh root
  • tidak dapat ditulis oleh grup atau pengguna lain
  • memiliki nama tanpa titik '.' atau karakter khusus lainnya selain '-' dan '_' .

Yang terakhir sering menyakiti pengguna yang tidak menaruh curiga; khususnya skrip apa pun di salah satu folder ini bernama whatever.sh , mycron.py , testfile.pl , dll. tidak dieksekusi, selamanya.

Dalam pengalaman saya, poin khusus ini sejauh ini merupakan alasan paling sering untuk cronjob non-eksekusi pada Debian dan turunannya.

Lihat man cron untuk detail lebih lanjut, jika perlu.

Solusi 3:

Jika cronjobs Anda berhenti berfungsi, periksa apakah kata sandi Anda belum kedaluwarsa., karena setelah itu, semua tugas cron berhenti.
Akan ada pesan di /var/log/messages mirip dengan yang di bawah ini yang menunjukkan masalah dengan mengautentikasi pengguna:

(username) FAILED to authorize user with PAM (Authentication token is no longer valid; new one required)

Solusi 4:

Jadwal yang tidak biasa dan tidak teratur

Cron dianggap sebagai penjadwal yang sangat mendasar dan sintaksnya tidak memungkinkan administrator untuk merumuskan jadwal yang sedikit lebih tidak biasa dengan mudah.

Pertimbangkan pekerjaan berikut yang umumnya akan dijelaskan ke "run command setiap 5 menit" :

*/5 * * * * /path/to/your/command

versus:

*/7 * * * * /path/to/your/command

yang tidak selalu jalankan command setiap 7 menit .

Ingat bahwa / karakter dapat digunakan untuk memperkenalkan langkah tetapi langkah itu tidak melampaui akhir rangkaian, mis. */7 yang cocok setiap menit ke-7 dari menit 0-59 yaitu 0,7,14,21,28,35,42,49,56 tetapi antara satu jam dan berikutnya akan ada hanya 4 menit antara batch , setelah 00:56 seri baru dimulai dari 01:00 , 01:07 dll. (dan kumpulan tidak akan berjalan di 01:03 , 01:10 , 01:17 dll.).

Apa yang harus dilakukan?

Buat beberapa kelompok

Daripada satu cron job, buat beberapa batch yang digabungkan menghasilkan jadwal yang diinginkan.

Misalnya untuk menjalankan batch setiap 40 menit (00:00, 00:40, 01:20, 02:00 dll.) buat dua batch, satu yang berjalan dua kali pada jam genap dan yang kedua hanya berjalan pada jam ganjil:

# The following lines create a batch that runs every 40 minutes i.e.

# runs on   0:00, 0:40,        02:00, 02:40         04:00 etc to 22:40
0,40 */2 * * * /path/to/your/command

# runs on               01:20,               03:20,       etc to 23:20
20 1/2 * * * /path/to/your/command

# Combined: 0:00, 0:40, 01:20, 02:00, 02:40, 03:20, 04:00 etc.

Jalankan kumpulan Anda lebih jarang

Daripada menjalankan batch Anda setiap 7 menit, yang merupakan jadwal yang sulit untuk dipecah menjadi beberapa batch, jalankan saja setiap 10 menit.

Mulai batch Anda lebih sering (tetapi cegah beberapa batch berjalan secara bersamaan)

Banyak jadwal aneh berkembang karena waktu proses batch meningkat/berfluktuasi dan kemudian batch dijadwalkan dengan sedikit margin keamanan tambahan untuk mencegah proses berikutnya dari batch yang sama tumpang tindih dan berjalan secara bersamaan.

Alih-alih, pikirkan secara berbeda dan buat cronjob yang akan gagal dengan baik ketika proses sebelumnya belum selesai, tetapi akan berjalan sebaliknya. Lihat T&J ini:

* * * * * /usr/bin/flock -n /tmp/fcj.lockfile /usr/local/bin/frequent_cron_job 

Itu akan segera memulai proses baru setelah proses /usr/local/bin/frequent_cron_job sebelumnya telah selesai.

Mulai batch Anda lebih sering (tetapi keluar dengan anggun saat kondisinya tidak tepat)

Karena sintaks cron terbatas, Anda dapat memutuskan untuk menempatkan kondisi dan logika yang lebih kompleks dalam tugas batch itu sendiri (atau dalam skrip pembungkus di sekitar pekerjaan batch yang ada). Itu memungkinkan Anda untuk memanfaatkan kemampuan lanjutan dari bahasa skrip favorit Anda, untuk mengomentari kode Anda dan akan mencegah konstruksi yang sulit dibaca di entri crontab itu sendiri.

Di bash, seven-minute-job kemudian akan terlihat seperti sesuatu seperti:

#!/bin/bash
# seven-minute-job
# This batch will only run when 420 seconds (7 min) have passed
# since the file /tmp/lastrun was either created or updated

if [ ! -f /tmp/lastrun ] ; then
    touch /tmp/lastrun
fi

if [ $(( $(date +%s) - $(date -r /tmp/lastrun +%s) )) -lt 420 ] ; then
     # The minimum interval of 7 minutes between successive batches hasn't passed yet.
    exit 0
fi

####  Start running your actual batch job below
  
/path/to/your/command

#### actual batch job is done, now update the time stamp
date > /tmp/lastrun
#EOF

Yang kemudian dapat Anda (coba) jalankan dengan aman setiap menit:

* * * * * /path/to/your/seven-minute-job

Masalah yang berbeda, tetapi serupa akan menjadwalkan batch untuk dijalankan pada hari Senin pertama setiap bulan (atau Rabu kedua) dll. Cukup jadwalkan batch untuk dijalankan setiap hari Senin dan keluar saat tanggal bukan antara 1 atau 7 dan hari minggu ini bukan hari Senin.

#!/bin/bash
# first-monday-of-the-month-housekeeping-job

# exit if today is not a Monday (and prevent locale issues by using the day number) 
if [ $(date +%u) != 1 ] ; then
  exit 0
fi

# exit if today is not the first Monday
if [ $(date +%d) -gt 7 ] ; then
  exit 0
fi

####  Start running your actual batch job below
  
/path/to/your/command

#EOF

Yang kemudian dapat Anda (coba) jalankan dengan aman setiap hari Senin:

0 0 * * 1 /path/to/your/first-monday-of-the-month-housekeeping-job

Jangan gunakan cron

Jika kebutuhan Anda kompleks, Anda dapat mempertimbangkan untuk menggunakan produk yang lebih canggih yang dirancang untuk menjalankan jadwal yang kompleks (didistribusikan melalui beberapa server) dan yang mendukung pemicu, ketergantungan pekerjaan, penanganan kesalahan, coba ulang dan coba lagi pemantauan, dll. Jargon industri akan menjadi "perusahaan " penjadwalan tugas dan/atau "otomatisasi beban kerja".

Solusi 5:

khusus PHP

Jika Anda memiliki beberapa tugas cron seperti:

php /bla/bla/something.php >> /var/logs/somelog-for-stdout.log

Dan jika terjadi kesalahan diharapkan, bahwa mereka akan dikirimkan kepada Anda, tetapi tidak -- periksa ini.

PHP secara default tidak mengirim kesalahan ke STDOUT. @lihat https://bugs.php.net/bug.php?id=22839

Untuk memperbaikinya, tambahkan di cli`s php.ini atau di baris Anda (atau di pembungkus bash Anda untuk PHP) ini:

  • --define display_startup_errors=1
  • --define display_errors='stderr'

Pengaturan ke-1 akan memungkinkan Anda memiliki fatal seperti 'Memory oops' dan ke-2 -- untuk mengalihkan semuanya ke STDERR. Hanya setelah Anda bisa tidur nyenyak karena semua akan dikirim ke email root Anda, bukan hanya login.


Linux
  1. Mengapa Data Penting Dan Bagaimana Cara Melindunginya

  2. Linux – Mengapa Kami Menggunakan Su – Dan Bukan Hanya Su?

  3. Mengapa Scp Sangat Lambat Dan Bagaimana Cara Mempercepatnya?

  1. Mengapa Saya Tidak Dapat Membagi File .ape?

  2. Bagaimana kerja jarak jauh dan perencanaan kesinambungan bisnis dapat mengurangi dampak COVID-19 (Coronavirus)?

  3. Bagaimana saya bisa memeriksa file yang ada dan menjalankan perintah jika tidak?

  1. Redis sebagai Cache:Cara Kerja dan Mengapa Menggunakannya

  2. Bagaimana saya bisa membuat 'diff -X' mengabaikan jalur tertentu dan bukan nama file?

  3. Bagaimana saya bisa memasang partisi pada setiap reboot?