Bagaimana saya bisa memberi tahu cron untuk menjalankan perintah setiap hari (aneh / genap)

45

Saat mengkonfigurasi cron untuk menjalankan perintah setiap hari menggunakan bidang "Day of Month", seperti:

1 22 */2 * * COMMAND

itu berjalan setiap kali hari dalam bulan ganjil: 1,3,5,7,9 dan seterusnya.

Bagaimana saya bisa mengkonfigurasi cron untuk berjalan pada hari-hari dalam bulan yang bahkan seperti 2,6,8,10 dan seterusnya (tanpa menentukan secara harfiah, yang bermasalah karena setiap bulan memiliki jumlah hari yang berbeda dalam bulan)?

freddie
sumber

Jawaban:

60

Sintaks yang Anda coba sebenarnya ambigu. Tergantung pada berapa hari dalam sebulan, beberapa bulan itu akan berjalan pada hari-hari ganjil dan beberapa di genap. Ini karena cara penghitungannya mengambil jumlah total kemungkinan dan membaginya. Anda dapat menunggangi perilaku strage-ish ini dengan menentukan rentang hari secara manual dan menggunakan jumlah hari yang ganjil atau genap. Karena bahkan skrip harian tidak akan pernah berjalan pada hari ke-31 dari bulan yang lebih lama, Anda tidak kehilangan apa pun menggunakan 30 hari sebagai basis untuk even-days, dan dengan menentukan secara khusus untuk membaginya seolah-olah ada 31 hari Anda dapat memaksa Eksekusi -hari.

Sintaksnya akan terlihat seperti ini:

# Will only run on odd days:
0 0 1-31/2 * * command

# Will only run on even days:
0 0 2-30/2 * * command

Kekhawatiran Anda tentang bulan yang tidak memiliki jumlah hari yang sama tidak penting di sini karena tidak ada bulan yang memiliki LEBIH BANYAK hari daripada ini dan untuk Februari yang buruk, rentang tanggal tidak akan pernah cocok dengan satu atau dua hari terakhir, tetapi tidak ada salahnya memiliki terdaftar.

Satu-satunya 'gotcha' untuk pendekatan ini adalah bahwa jika Anda berada pada siklus hari ganjil, bulan berikutnya dengan 31 hari perintah Anda juga akan berjalan pada bulan pertama bulan itu. Demikian juga jika Anda memaksakan siklus genap, setiap tahun kabisat akan menyebabkan siklus tiga hari dan akhir Februari. Anda tidak dapat benar-benar menyiasati kenyataan bahwa pola reguler "setiap hari" tidak selalu akan jatuh pada hari genap atau ganjil dalam setiap bulan dan dengan cara apa pun Anda memaksakan ini, Anda akan memiliki perpanjangan tambahan atau kehilangan batas antara bulan dengan jumlah hari yang tidak cocok.

Caleb
sumber
1
Terima kasih, tetapi apa yang akan terjadi pada bulan-bulan seperti Februari di mana Anda hanya memiliki 28 hari? Bintang itu sebenarnya mengurus hal itu - tetapi memang ambigu.
freddie
3
@ Freddie: Lihat jawaban saya yang diedit ... tapi ini bukan masalah karena nilai di luar rentang hanya akan diabaikan, tidak ada yang akan terjadi pada tanggal 30 atau 31 Februari. Pernah. Anda dapat menentukan secara manual dengan daftar suka 0,2,4...,30,32,34dan itu tidak masalah, nilai di luar rentang tidak akan pernah cocok.
Caleb
1
Terima kasih! Saya mengerti, terima kasih atas jawaban yang informatif!
freddie
3
Pada server Ubuntu 8.04, tampaknya sintaks yang menggunakan hari nol bulan tidak valid (hari buruk bulan). Sintaksis berikut, bagaimanapun, diterima:0 0 2-30/2 * * command
1
Fedora dan RHEL 5,6,7 juga tidak suka 0 sebagai hari dalam sebulan. Seperti yang ditunjukkan oleh user31053: 0 0 2-30/2 * * commandberfungsi seperti yang diharapkan.
NoelProf
2

Saya pikir kemungkinan menggunakan hari dalam setahun, seperti ini:

# for odd days
test $(((`date +%j` % 2))) != 0 && command

# for even days
test $(((`date +%j` % 2))) == 0 && command

Ini diuji untuk sistem Unix dan Linux.

Jordi
sumber
Saya lebih suka jawaban ini karena melompati masalah dengan jumlah hari ganjil dengan beberapa bulan. Pokoknya saya sarankan notasi dolar sebagai gantinya backticks:test $(($(date +%j) % 2)) == 0 && command
caligari
Saya telah meninjau bahwa% j bukan tanggal Julian, jadi kode terbaik yang menghindari transisi Tahun Baru harus dihitung dengan detik:test $(($(date +%s) / 86400 % 2)) == 0 && command
caligari
Terima kasih atas komentarnya! Proposal kami bekerja untuk kami seperti pesona. Kami menggunakan skema itu untuk menjalankan crons setiap hari pada node server yang berbeda, semua mereka berbagi crontab yang sama, tetapi skrip hanya memungkinkan untuk menjalankan skrip pada salah satu dari mereka. Namun, jika kami perlu membuatnya lebih spesifik, kami akan mempertimbangkan proposal Anda. Terima kasih!!!
Jordi
1

Mari kita periksa setiap hari apakah ini "lainnya" :-) ( bcdiperlukan program)

0 0 * * * test $(echo `date +%s` / 86400 % 2 == 0 |bc) -eq 0 && command

(Saya tidak yakin kode tersebut muncul dengan benar. Bagian date +%sini berada di antara apostrof belakang.)

pengguna37264
sumber
Ini akan berjalan setiap hari tetapi tidak menjawab pertanyaan! Itu masih akan berjalan kadang-kadang pada hari-hari ganjil kadang-kadang pada hari genap tergantung pada bulan. Ini memiliki hasil yang sama dengan kode dalam pertanyaan, Anda baru saja tiba pada hasilnya dengan melakukan matematika Anda sendiri pada detik sejak zaman. Ini berjalan pada hari-hari genap sejak zaman tetapi tidak pada hari-hari genap kalender kita.
Caleb
1

Secara umum, saya akan menjalankannya setiap hari dan skrip menggunakan logika untuk menentukan apakah harus dijalankan hari ini.

Membuat file status yang sederhana memberitahu kapan terakhir kali dijalankan dan kemudian compairing akan bekerja dengan sangat mudah.

Jika perlu dijalankan melalui sumber yang berbeda, buatlah itu bergantung pada argumen.

Klas Mattsson
sumber