Cron, pastikan hanya satu instance

9

Apakah ada cara untuk menjalankan skrip setiap menit (atau 2, atau 5, dll), tetapi hanya jika skrip belum berjalan?

Kami memiliki serangkaian skrip yang perlu dijalankan setiap menit. Kadang-kadang mereka mungkin mulai dan selesai dalam sedetik, di lain waktu mereka mungkin berjalan selama 5 menit.

Cara kami saat ini untuk menghindari eksekusi simultan adalah dengan menetapkan is_runningbendera di setiap skrip, dan keluar jika masih diaktifkan. Tapi ini sedikit tidak bisa diandalkan (yaitu, kesalahan fatal akan menyebabkan bendera tetap diaktifkan bahkan setelah skrip dihentikan).

Kita bisa menulis manajer kecil kita sendiri, tetapi saya bertanya-tanya apakah ada solusi yang lebih modis yang sudah ada.

chroder
sumber
+1 Saya tertarik pada ini juga. Saya tidak tahu jawabannya, namun saya tertarik dengan solusi yang mungkin.
Saif Bechan
Seorang cron yang sangat halus mencium banyak "make me a daemon"
AD7six

Jawaban:

8

cara yang lebih baik adalah menggunakan flockalih-alih pidfile. periksa halaman manual: flock (1) . Keuntungannya adalah tidak peduli bagaimana proses selesai / mati, kuncinya tetap ada.

Javier
sumber
3

Saya cenderung setuju dengan jawaban file pid Warner. Namun, apakah fitur Anacron berikut menyelesaikan ini?

-s
    Serialize execution of jobs. Anacron will not start a new job before the previous one finished. 

Saya belum mengujinya sendiri, saya tidak menemukan dokumentasi anacron cukup menyeluruh ...

Jika Anda ingin menjadi sangat malas ;-) Anda hanya dapat memiliki skrip keluar jika memahami keluaran ps mengembalikan proses sebagai berjalan. Tetapi file kunci / pid adalah yang terbaik.

Kyle Brandt
sumber
anacron adalah versi yang lebih baru dari cron, sehingga memiliki lebih banyak fitur daripada standar yang lama. tentang 'bagaimana', itu mungkin mendaftarkan penangan SIGCHLD, yang dipicu ketika proses anak meninggal. dengan demikian ia dapat melacak berlari anak dan hanya melewatkan pekerjaan itu.
Javier
@ Javier: Saya tidak setuju dengan "anacron adalah versi yang lebih baru dari cron, jadi ia memiliki lebih banyak fitur daripada standar yang lama." Ada beberapa tumpang tindih antara apa anacrondan apa yang crondilakukan, tetapi mereka memecahkan masalah yang berbeda. Dengan menggunakan cron, bagaimana Anda memulai pekerjaan yang tidak terjawab karena mesin mati? Dengan menggunakan anacron, bagaimana Anda memulai pekerjaan setiap 25 Desember atau setiap 5 menit? (Tentu saja, Anda dapat memecahkan masalah skrip, tapi bukan itu yang saya bicarakan.)
Dijeda hingga pemberitahuan lebih lanjut.
@Kyle: Opsi itu menyebabkan berbagai pekerjaan dijadwalkan untuk berjalan pada saat yang sama untuk menjalankan satu per satu. Ini mungkin bekerja untuk kebutuhan OP, tetapi itu akan memblokir pekerjaan lain atau pekerjaan lain akan memblokirnya. Juga, anacrontidak berjalan pada periode yang lebih pendek dari satu hari.
Dijeda sampai pemberitahuan lebih lanjut.
@Dennis Williamson: saya kira Anda benar, saya belum memeriksa detail riwayatnya. Tapi tetap saya kira Anda akan setuju bahwa proyek anacron dimulai setelah cron cukup banyak didirikan, dan terinspirasi olehnya; oleh karena itu tidak mengherankan bahwa ia memiliki fitur yang tidak dimiliki cron. Juga, pertanyaan aslinya adalah tentang cron
Javier
1

Itu solusi yang tepat untuk pendekatan itu. Biasanya, file pid akan digunakan dan tes pid akan dilakukan terhadap proses untuk memastikan itu berjalan. Jika basi, file kunci akan dihapus dan proses akan tetap berjalan.

Setiap kecerdasan tambahan biasanya akan ditulis dalam perangkat lunak itu sendiri, sebagai daemon, sebagai lawan berjalan di cron.

Warner
sumber
1

Jika skrip Anda dikodekan dalam bahasa yang mendukung syscall flock (2), maka Anda bisa flock () file kunci dengan panggilan fungsi juga. Contoh:

Jika Anda terjebak dengan Bash atau bahasa skrip lain yang tidak mendukung ini, solusi yang sudah diajukan dengan flock (1) juga baik-baik saja.

PS Dalam hal apa pun, Anda harus membuat file kunci yang terpisah hanya sekali (jika belum ada), dan jangan pernah menghapusnya. Direktori "/ var / lock" adalah tempat yang baik untuk file seperti itu.

famzah
sumber
0

Ini adalah solusi jika skrip Anda berjalan dalam python (atau Anda dapat membuat perintah python untuk dijalankan sebelum perintah berikutnya) - Saya mengalami masalah yang sama minggu lalu, dan meskipun saya menemukan beberapa solusi yang baik, saya memutuskan untuk membuat sangat paket python sederhana dan bersih dan mengunggahnya ke PyPI. Anda pasti bisa mengunci __file__agar tidak perlu berpikir untuk memberinya nama sumber daya khusus untuk dikunci.

Instal dengan: pip install quicklock

Menggunakannya sangat sederhana:

[nate@Nates-MacBook-Pro-3 ~/live] python
Python 2.7.6 (default, Sep  9 2014, 15:04:36)
[GCC 4.2.1 Compatible Apple LLVM 6.0 (clang-600.0.39)] on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>> from quicklock import singleton
>>> # Let's create a lock so that only one instance of a script will run
...
>>> singleton('hello world')
>>>
>>> # Let's try to do that again, this should fail
...
>>> singleton('hello world')
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/Users/nate/live/gallery/env/lib/python2.7/site-packages/quicklock/quicklock.py", line 47, in singleton
    raise RuntimeError('Resource <{}> is currently locked by <Process {}: "{}">'.format(resource, other_process.pid, other_process.name()))
RuntimeError: Resource <hello world> is currently locked by <Process 24801: "python">
>>>
>>> # But if we quit this process, we release the lock automatically
...
>>> ^D
[nate@Nates-MacBook-Pro-3 ~/live] python
Python 2.7.6 (default, Sep  9 2014, 15:04:36)
[GCC 4.2.1 Compatible Apple LLVM 6.0 (clang-600.0.39)] on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>> from quicklock import singleton
>>> singleton('hello world')
>>>
>>> # No exception was thrown, we own 'hello world'!

Lihatlah: https://pypi.python.org/pypi/quicklock

Nate Ferrero
sumber