Saya perlu memulai cronjob setiap hari, tetapi satu jam kemudian setiap hari. Apa yang saya miliki sejauh ini berfungsi sebagian besar, kecuali untuk 1 hari dalam setahun:
0 0 * * * sleep $((3600 * (10#$(date +\%j) \% 24))) && /usr/local/bin/myprog
Ketika hari tahun 365, pekerjaan akan dimulai pukul 5:00, tetapi hari berikutnya (tidak termasuk tahun kabisat) akan memiliki hari dalam setahun sebagai 1, sehingga pekerjaan akan dimulai pada 1:00. Bagaimana saya bisa menyingkirkan kasing sudut ini?
Jawaban:
Solusi pilihan saya adalah memulai pekerjaan setiap jam tetapi minta skrip itu sendiri memeriksa apakah sudah waktunya untuk menjalankan atau tidak dan keluar tanpa melakukan apa pun 24 kali dari 25.
crontab:
di bagian atas
myprog
:Jika Anda tidak ingin membuat perubahan apa pun pada skrip itu sendiri, Anda juga dapat memberi tanda "waktu untuk menjalankan" di entri crontab tetapi itu membuat garis panjang yang tidak enak dilihat:
sumber
date
kembali dari kernel1ms
sebelum waktu yang Anda harapkan skrip dijalankan, cek akan memberikan hasil yang salah.ntpd
, itu berusaha keras untuk hanya mematikan jam, bukan melompat, khususnya untuk menghindari masalah semacam ini, tetapi Anda benar,ntpdate
kadang-kadang (atau ) kadang-kadang dapat melompat mundur waktu. Adapuncron
salah perhitungan penundaan tidurnya, saya cukup yakin itu akan dianggap bug! Namun, poin yang diambil, dan solusinya adalah untuk menjadwalkan pekerjaan 30 menit melewati jam yang cenderung menyebabkan masalah ... Atau tambahkan ± 1800 dalam ekspresi aritmatika sebelum mengambil reamainder mod 3600.Jika sistem Anda memiliki systemd, Anda dapat menggunakan event timer untuk ini. Cukup tentukan layanan baru , yang harus berisi perintah / tugas yang ingin Anda jalankan, dan kemudian buat acara pengatur waktu dengan
OnUnitActiveSec
opsi:Gunakan nama yang sama untuk file, kecuali bahwa bukan
.service
Anda gunakan.timer
.Mensintesis:
job.service
di/etc/systemd/system/
direktori.systemctl status job.service
.job.timer
dalam/etc/systemd/system/
.Isi dengan informasi yang diperlukan:
systemctl list-timers
sumber
Jika Anda tidak keberatan menggunakan sesuatu selain cronjobs, saya akan menyarankan utilitas yang kurang dikenal
at
. Cukup tulis skrip pembungkus yang kedua jadwal itu sendiri akan dijalankan dalam 25 jam, dan kemudian panggil program Anda. Ini tampaknya menjadi solusi terbersih.Misalnya, Anda bisa menulis ini di ~ / script.sh:
Dan kemudian jalankan
bash ~/script.sh
sekali saja.Terima kasih kepada @HalosGhost untuk ide penjadwalan pekerjaan sekali dalam 25 jam.
sumber
at
untuk tujuan ini: (1) jika pekerjaan gagal dieksekusi dengan benar bahkan sekali, itu juga mungkin gagal menjadwal ulang sendiri dan kemudian bukan hanya eksekusi berikutnya tetapi semua eksekusi di masa depan secara efektif dibatalkan sampai pemberitahuan manusia, dan (2) karena pekerjaan itu membutuhkan waktu non-nol untuk berjalan, menggunakan naifnow + 25 hours
berarti akan berjalan beberapa detik (atau lebih) setiap kali, dan jika kelambatan ini akan menumpuk dari waktu ke waktu, membuatnya akhirnya berjalan di sepenuhnya salah waktu.at
terbatas pada menit dan memulai semua pekerjaan pada [waktu]: 00.at
pekerjaan hal pertama di script menghindari masalah tersebut. Sekalipun demikian, jika kesalahan terjadi maka seluruh rantai terputus, yang mungkin atau mungkin tidak diinginkan: jika use case "hanya jalankan ini ketika berfungsi", tidak memulai kembali adalah fitur yang hebat. Tetapi jika use case adalah "selalu berjalan, bahkan jika yang terakhir gagal" makaat
bukan alat yang tepat.