Ok jadi saya punya cron yang harus saya jalankan setiap 30 detik.
Inilah yang saya miliki:
*/30 * * * * /bin/bash -l -c 'cd /srv/last_song/releases/20120308133159 && script/rails runner -e production '\''Song.insert_latest'\'''
Ini berjalan, tetapi apakah ini berjalan setiap 30 menit atau 30 detik?
Juga, saya telah membaca bahwa cron mungkin bukan alat terbaik untuk digunakan jika saya sering menjalankannya. Apakah ada alat lain yang lebih baik yang bisa saya gunakan atau instal di Ubuntu 11.04 yang akan menjadi pilihan yang lebih baik? Apakah ada cara untuk memperbaiki cron di atas?
ubuntu
cron
scheduled-tasks
Matt Elhotiby
sumber
sumber
Jawaban:
Anda memiliki
*/30
di menit specifier - yang berarti setiap menit namun dengan langkah 30 (dengan kata lain, setiap setengah jam). Karenacron
tidak turun ke resolusi sub-menit, Anda perlu menemukan cara lain.Satu kemungkinan, meskipun ini sedikit kludge (a) , adalah memiliki dua pekerjaan, satu diimbangi dengan 30 detik:
Anda akan melihat saya telah menambahkan komentar dan diformat untuk memastikan mudahnya menyinkronkannya.
Kedua
cron
pekerjaan benar-benar berjalan setiap menit tetapi yang terakhir akan menunggu setengah menit sebelum mengeksekusi "daging" pekerjaan/path/to/executable
,.Untuk
cron
opsi (non- berbasis) lainnya, lihat jawaban lain di sini, terutama yang menyebutkanfcron
dansystemd
. Ini mungkin lebih baik dengan asumsi sistem Anda memiliki kemampuan untuk menggunakannya (seperti menginstalfcron
atau memiliki distrosystemd
dengannya).Jika Anda tidak ingin menggunakan solusi kludgy, Anda dapat menggunakan solusi berbasis loop dengan sedikit modifikasi. Anda masih harus mengelola agar proses Anda tetap berjalan dalam beberapa bentuk tetapi, setelah diurutkan, skrip berikut akan berfungsi:
Caranya adalah dengan menggunakan
sleep 30
tetapi untuk memulainya di latar belakang sebelum payload Anda berjalan. Kemudian, setelah payload selesai, tunggu saja latar belakangnyasleep
selesai.Jika payload mengambil
n
detik (di manan <= 30
), menunggu setelah payload kemudian akan menjadi30 - n
detik. Jika dibutuhkan lebih dari 30 detik, maka siklus berikutnya akan tertunda hingga payload selesai, tetapi tidak lagi.Anda akan melihat bahwa saya memiliki kode debug di sana untuk memulai pada batas satu menit untuk membuat output awalnya lebih mudah diikuti. Saya juga secara bertahap meningkatkan waktu payload maksimum sehingga pada akhirnya Anda akan melihat payload melebihi waktu siklus 30 detik (garis kosong tambahan adalah output sehingga efeknya jelas).
Contoh dijalankan berikut (di mana siklus biasanya dimulai 30 detik setelah siklus sebelumnya):
Jika Anda ingin menghindari solusi kludgy, ini mungkin lebih baik. Anda masih membutuhkan
cron
pekerjaan (atau yang setara) untuk mendeteksi secara berkala jika skrip ini berjalan dan, jika tidak, mulai saja. Tapi skrip itu sendiri yang mengatur waktu.(a) Beberapa teman kerja saya akan mengatakan bahwa kludges adalah keahlian saya :-)
sumber
Kamu tidak bisa Cron memiliki rincian 60 detik.
sumber
&&
bukannya( ; )
.&&
Operator sirkuit pendek, sehingga perintah berikutnya dalam rantai tersebut tidak dijalankan jika sebelumnya gagal.Granularity Cron dalam hitungan menit dan tidak dirancang untuk bangun setiap
x
detik untuk menjalankan sesuatu. Jalankan tugas berulang Anda dalam satu lingkaran dan itu akan melakukan apa yang Anda butuhkan:sumber
while [ true ]
menyebabkan Anda memiliki banyak contoh skrip yang sama, karena cron akan memulai yang baru setiap menit?sleep $remainingTime
mana yang tersisa TimeTime adalah 30 dikurangi waktu pekerjaan (dan tutup pada nol jika butuh> 30 detik). Jadi, Anda mengambil waktu sebelum dan sesudah pekerjaan yang sebenarnya, dan menghitung perbedaannya.Jika Anda menjalankan OS Linux baru-baru ini dengan SystemD, Anda dapat menggunakan unit SystemD Timer untuk menjalankan skrip Anda pada tingkat granularitas yang Anda inginkan (secara teoritis hingga nanodetik), dan - jika Anda mau - aturan peluncuran yang jauh lebih fleksibel daripada yang pernah diizinkan Cron . Tidak
sleep
diperlukan kludgesDibutuhkan sedikit lebih banyak untuk mengatur daripada satu baris dalam file cron, tetapi jika Anda membutuhkan sesuatu yang lebih baik daripada "Setiap menit", itu sepadan dengan usaha.
Model timer SystemD pada dasarnya adalah ini: timer adalah unit yang memulai unit layanan ketika timer berlalu .
Jadi untuk setiap skrip / perintah yang ingin Anda jadwalkan, Anda harus memiliki unit layanan dan kemudian unit timer tambahan. Satu unit pengatur waktu dapat mencakup beberapa jadwal, sehingga Anda biasanya tidak memerlukan lebih dari satu pengatur waktu dan satu layanan.
Berikut adalah contoh sederhana yang mencatat "Hello World" setiap 10 detik:
/etc/systemd/system/helloworld.service
:/etc/systemd/system/helloworld.timer
:Setelah mengatur unit-unit ini (dalam
/etc/systemd/system
, seperti yang dijelaskan di atas, untuk pengaturan seluruh sistem, atau pada~/.config/systemd/user
untuk pengaturan khusus pengguna), Anda perlu mengaktifkan timer (bukan layanan) dengan menjalankansystemctl enable --now helloworld.timer
(--now
flag juga memulai timer segera, jika tidak, itu hanya akan mulai setelah boot berikutnya, atau login pengguna).Bidang
[Timer]
bagian yang digunakan di sini adalah sebagai berikut:OnBootSec
- Mulai layanan ini beberapa detik setelah setiap boot.OnUnitActiveSec
- Mulai layanan ini beberapa detik setelah layanan terakhir kali dimulai. Inilah yang menyebabkan timer berulang dan berperilaku seperti tugas cron.AccuracySec
- mengatur keakuratan timer. Pengatur waktu hanya seakurat yang ditetapkan bidang ini, dan standarnya adalah 1 menit (mengemulasi cron). Alasan utama untuk tidak menuntut keakuratan terbaik adalah untuk meningkatkan konsumsi daya - jika SystemD dapat menjadwalkan proses berikutnya untuk bertepatan dengan peristiwa lain, ia perlu membangunkan CPU lebih jarang. Dalam1ms
contoh di atas tidak ideal - Saya biasanya mengatur keakuratan1
(1 detik) dalam pekerjaan terjadwal sub-menit saya, tetapi itu berarti bahwa jika Anda melihat log yang menunjukkan pesan "Hello World", Anda akan melihat bahwa seringkali terlambat 1 detik. Jika Anda setuju dengan itu, saya sarankan untuk mengatur keakuratan 1 detik atau lebih.Seperti yang mungkin Anda perhatikan, timer ini tidak meniru Cron dengan baik - dalam arti bahwa perintah tidak dimulai pada awal setiap periode jam dinding (yaitu tidak dimulai pada detik ke-10 pada jam, kemudian tanggal 20 dan seterusnya). Alih-alih hanya terjadi ketika timer elips. Jika sistem di-boot pada 12:05:37, maka pada saat perintah dijalankan akan pada 12:05:47, kemudian pada 12:05:57, dll. Jika Anda tertarik pada keakuratan jam dinding aktual, maka Anda dapat ingin mengganti
OnBootSec
danOnUnitActiveSec
ladang dan bukan menetapkanOnCalendar
aturan dengan jadwal yang Anda inginkan (yang sejauh yang saya mengerti tidak bisa lebih cepat dari 1 detik, menggunakan format kalender). Contoh di atas juga dapat ditulis sebagai:Catatan terakhir: seperti yang Anda duga,
helloworld.timer
unit memulaihelloworld.service
unit karena mereka memiliki nama yang sama (minus akhiran tipe unit). Ini adalah default, tetapi Anda dapat menimpanya dengan mengaturUnit
bidang untuk[Timer]
bagian tersebut.Lebih banyak detail berdarah dapat ditemukan di:
man systemd.timer
man systemd.time
man systemd.service
man system.exec
sumber
Tidak perlu dua entri cron, Anda dapat memasukkannya ke dalam satu dengan:
jadi dalam kasus Anda:
* * * * * /bin/bash -l -c "cd /srv/last_song/releases/20120308133159 && script/rails runner -e production '\''Song.insert_latest'\'' ; sleep 30 ; cd /srv/last_song/releases/20120308133159 && script/rails runner -e production '\''Song.insert_latest'\''"
sumber
Anda dapat memeriksa jawaban saya untuk pertanyaan serupa ini
Pada dasarnya, saya telah memasukkan di sana skrip bash bernama "runEvery.sh" yang dapat Anda jalankan dengan cron setiap 1 menit dan memberikan argumen sebagai perintah nyata yang ingin Anda jalankan dan frekuensi dalam detik di mana Anda ingin menjalankannya.
sesuatu seperti ini
* * * * * ~/bin/runEvery.sh 5 myScript.sh
sumber
Gunakan jam tangan:
sumber
$ watch --interval .10 php some_file.php
? atauwatch
hanya berfungsi dengan file .sh?--interval .30
tidak akan berjalan dua kali satu menit. Yaituwatch -n 2 "sleep 1 && date +%s"
akan bertambah setiap 3s.watch
dirancang untuk penggunaan terminal, jadi - selagi dapat bekerja tanpa terminal (dijalankan dengannohup
lalu logout) atau dengan terminal palsu (sepertiscreen
) - ia tidak memiliki biaya untuk perilaku seperti cron, seperti memulihkan dari kegagalan, memulai kembali setelah boot, dll.Pekerjaan Cron tidak dapat digunakan untuk menjadwalkan pekerjaan dalam interval detik. yaitu Anda tidak dapat menjadwalkan pekerjaan cron untuk berjalan setiap 5 detik. Alternatifnya adalah dengan menulis skrip shell yang menggunakan
sleep 5
perintah di dalamnya.Buat skrip shell every-5-seconds.sh menggunakan bash while, seperti ditunjukkan di bawah ini.
Sekarang, jalankan skrip shell ini di latar belakang menggunakan
nohup
seperti yang ditunjukkan di bawah ini. Ini akan terus mengeksekusi skrip bahkan setelah Anda keluar dari sesi Anda. Ini akan menjalankan skrip shell backup.sh Anda setiap 5 detik.sumber
backup.sh
berjalan 1,5 detik, itu akan dijalankan setiap 6,5 detik. Ada cara untuk menghindarinya, misalnyasleep $((5 - $(date +%s) % 5))
Gunakan fcron ( http://fcron.free.fr/ ) - memberi Anda rincian dalam hitungan detik dan jauh lebih baik dan lebih kaya fitur daripada cron (vixie-cron) dan juga stabil. Saya biasa membuat hal-hal bodoh seperti memiliki sekitar 60 skrip php yang berjalan pada satu mesin dalam pengaturan yang sangat bodoh dan masih melakukan tugasnya!
sumber
dalam dir
/etc/cron.d/
baru buat file
excute_per_30s
akan menjalankan cron setiap 30 detik
sumber
Saat ini saya menggunakan metode di bawah ini. Bekerja tanpa masalah.
Jika Anda ingin menjalankan setiap N detik kemudian X akan 60 / N dan Y akan N .
Terima kasih.
sumber
YOUR_COMMANDS
keYOUR_COMMANDS &
, sehingga perintah diluncurkan ke latar belakang, jika tidak, jika perintah mengambil lebih dari sepersekian detik - itu akan menunda peluncuran berikutnya. Jadi dengan X = 2 dan Y = 30, jika perintahnya memakan waktu 10 detik - itu akan diluncurkan pada menit dan kemudian 40 detik kemudian, bukannya 30. Kudus ke @paxdiablo./bin/bash -c
bagian (termasuk kutipan argumen) skrip hanya berjalan setiap menit, mengabaikan iterasi (dalam kasus sayaX=12
danY=5
).Pekerjaan Crontab dapat digunakan untuk menjadwalkan pekerjaan dalam hitungan menit / jam / hari, tetapi tidak dalam hitungan detik. Alternatifnya:
Buat skrip untuk dieksekusi setiap 30 detik:
Gunakan
crontab -e
dan crontab untuk menjalankan skrip ini:sumber
Anda dapat menjalankan skrip itu sebagai layanan, restart setiap 30 detik
Daftarkan layanan
Tempel di perintah di bawah ini
Muat ulang layanan
Aktifkan layanan
Mulai layanan
Periksa status layanan Anda
sumber
Terima kasih atas semua jawaban yang baik. Untuk membuatnya lebih sederhana, saya menyukai solusi campuran, dengan kontrol pada crontab dan pembagian waktu pada skrip. Jadi inilah yang saya lakukan untuk menjalankan skrip setiap 20 detik (tiga kali per menit). Garis crontab:
Naskah:
sumber
tulis satu skrip shell buat file .sh
nano every30second.sh
dan menulis skrip
kemudian atur cron untuk skrip ini crontab -e
(* * * * * /home/username/every30second.sh)
file .sh panggilan cron ini dalam setiap 1 menit & dalam perintah file .sh dijalankan 2 kali dalam 1 menit
jika Anda ingin menjalankan skrip selama 5 detik, ganti 30 dengan 5 dan ubah untuk loop seperti ini:
For (( i=1; i <= 12; i++ ))
Ketika Anda memilih untuk setiap detik maka hitung 60 / detik Anda dan tulis di For loop
sumber
Saya hanya punya tugas serupa untuk dilakukan dan menggunakan pendekatan berikut:
Saya perlu melakukan kill -3 berkala (untuk mendapatkan jejak stack dari suatu program) setiap 30 detik selama beberapa jam.
Ini di sini untuk memastikan bahwa saya tidak kehilangan pelaksanaan arloji jika saya kehilangan shell (masalah jaringan, windows crash dll ...)
sumber
Lihatlah sering-cron - ini sudah tua tetapi sangat stabil dan Anda dapat mundur ke mikro-detik. Pada titik ini, satu-satunya hal yang akan saya katakan menentangnya adalah bahwa saya masih mencoba mencari cara menginstalnya di luar init.d tetapi sebagai layanan systemd asli, tetapi tentu saja hingga Ubuntu 18 itu berjalan hanya baik masih menggunakan init.d (jarak dapat bervariasi pada versi terakhir). Ini memiliki keuntungan tambahan (?) Untuk memastikan bahwa ia tidak akan menelurkan contoh lain dari skrip PHP kecuali yang sebelumnya telah selesai, yang mengurangi potensi masalah kebocoran memori.
sumber
Jalankan dalam loop shell, contoh:
sumber
60
seharusnya a30
, Anda mungkin ingin memindahkannyawget
di dalamif
pernyataan, jika tidak dieksekusi setiap detik. Bagaimanapun, saya tidak yakin bagaimana ini lebih baik daripada hanya satusleep 30
. Jika Anda memantau waktu UNIX yang sebenarnya daripada penghitung Anda, itu akan membuat perbedaan.