Soru Yinelenen cron işlerini engelle


Her dakika çalışmak için bir cron işi planladım ama bazen betiğin bitmesi bir dakikadan uzun sürüyor ve işlerin birbiri üzerinde "istiflenmeye" başlamasını istemiyorum. Bu bir eşzamanlılık problemi sanırım - yani komut dosyası yürütme, karşılıklı olarak özel olması gerekiyor.

Ben senaryoyu yaptım sorunu çözmek için belirli bir dosyanın varlığını arayın ("lockfile.txt") ve varsa çıkar veya touch eğer değilse. Ama bu oldukça berbat bir semafor! Bilmem gereken en iyi uygulama var mı? Bunun yerine bir daemon yazmalı mıyım?


81
2017-11-09 11:32


Menşei




Cevaplar:


Bu özelliği otomatikleştiren, rahatsızlıklarını ve olası hataları kendinizin yapmasını engelleyen birkaç program var ve sahnenin arkasındaki sürüyü kullanarak bayat kilit probleminden de kaçının (bu sadece bir dokunuş kullanıyorsanız risktir) . Kullandım lockrun ve lckdo geçmişte, ama şimdi flock(1) (util-linux'un yeni sürümlerinde) harikadır. Kullanımı gerçekten çok kolay:

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

109
2017-11-09 11:57



lckdo, daha fazla sürüden kaldırılacak, şimdi sürü (1) kullanımda bulunuyor. Ve bu paket Linux sistemlerinde temel olarak zorunludur, bu yüzden varlığına güvenebilmelisiniz. Kullanım için aşağıya bakın. - jldugger
Evet, sürü şimdi tercih ettiğim seçenek. Cevabımı uygun bir şekilde bile güncelleyeceğim. - womble♦
Aradaki farkı bilen var mı flock -n file command ve flock -n file -c command ? - Nanne
@Nanne, emin olmak için kodu kontrol etmeliyim, ama benim eğitimli tahminim şu: -c Belirtilen komutu bir kabuk (manpage uyarınca), "çıplak" (non-c) sadece formu execverilen komut. Kabuğun içinden bir şey koymak, kabuk benzeri şeyler yapmanıza izin verir (örneğin, birden çok komutu çalıştırmak ; veya &&), ancak güvenilmeyen giriş kullanıyorsanız, kabuk genişletme saldırılarına da açılır. - womble♦
Bu (varsayımsal) bir argüman oldu frequent_cron_job Her dakika koşmaya çalıştığını gösteren komut. Faydası olmayan bir şey eklediğinden ve karışıklığa sebep olduğundan (kimsenin yıllar geçmediği sürece) onu çıkardım. - womble♦


Kabuğun en iyi yolu kullanmaktır akın (1)

(
  flock -x -w 5 99
  ## Do your stuff here
) 99>/path/to/my.lock

27
2017-11-09 11:45



Fd yönlendirme konusunda zor kullanmıyorum. Bu sadece inanılmaz derecede harika. - womble♦
Bash veya ZSH'de benim için ayrıştırma, aradaki boşluğu ortadan kaldırması gerek. 99 ve > İşte bu 99> /... - Kyle Brandt♦
@Javier: Bu zor ve arcane değil, sadece olduğu anlamına gelmez belgeli, zor ve arcane. - womble♦
Bu işlem devam ederken yeniden başlatırsanız veya işlemi bir şekilde öldürürseniz ne olur? Sonsuza dek kilitli olur mu? - Alex R
Bu yapının özel bir kilit oluşturduğunu anlıyorum ama bunun nasıl başarıldığının mekaniğini anlamıyorum. Bu cevapta '99'un işlevi nedir? Bunu açıklamak isteyen var mı lütfen? Teşekkürler! - Asciiom


Aslında, flock -n yerine kullanılabilir lckdo*, böylece çekirdek geliştiricilerinden kod kullanacaksınız.

İnşaa ediliyor Womble'ın örneğişöyle bir şey yazarsın:

* * * * * flock -n /some/lockfile command_to_run_every_minute

BTW, kodlara bakarak, hepsi flock, lockrun, ve lckdo Aynı şeyi yapın, bu yüzden sadece sizin için en uygun olanı.

* Yazım sırasındaki şöhretimden ötürü, önceki cevapları ne düzenleyeceğim ne de yorum yapabilirim, bunu ayrı bir cevap olarak yazmalıyım.


21
2017-11-19 22:43





Bir kilit dosyası kullanabilirsiniz. Komut tamamlandığında bu dosyayı oluşturun ve tamamlandığında silin. Komut, ana rutinini çalıştırmadan önce, kilit dosyasının mevcut olup olmadığını kontrol etmeli ve buna göre hareket etmelidir.

Lockfiles, Unix sistemlerinde initscripts ve diğer birçok uygulama ve yardımcı program tarafından kullanılır.


2
2017-11-09 11:36



bu sadece Gördüğüm gibi, kişisel olarak uygulamıştım. Bir OSS projesi için bakıcının önerisi olarak kullanmaktayım - warren


Bu, yanlış şeyi yaptığınızın da bir işareti olabilir. Eğer işleriniz o kadar sık ​​ve o kadar sık ​​çalışırsa, belki de bunu caydırmayı ve onu daemon tarzı bir program haline getirmeyi düşünmelisiniz.


1
2017-11-09 11:45



Ben buna yürekten katılmıyorum. Periyodik olarak çalışması gereken bir şeyiniz varsa, bunu bir daemon yapmak bir "fındık için bir balyoz" çözümü. Kazaları önlemek için bir kilitleme dosyası kullanmak, hiç bir zaman sorun yaşamadığım mükemmel bir çözümdür. - womble♦
@womble Katılıyorum; ama balyozla fındıkları parçalamayı severim! :-) - wzzrd


Komut dosyasının önceki çalışmanın tamamlanmasını beklemesini beklemesini istiyorsanız bunu belirtmemişsiniz. "İşlerin" birbirinin üzerine yığılmasını "istemiyorum", sanırım zaten çalışıyorsa komut dosyasının çıkmasını istediğinizi ima ediyorsunuz,

Yani, lckdo'ya veya benzerlerine güvenmek istemiyorsanız, bunu yapabilirsiniz:


PIDFILE=/tmp/`basename $0`.pid

if [ -f $PIDFILE ]; then
  if ps -p `cat $PIDFILE` > /dev/null 2>&1; then
      echo "$0 already running!"
      exit
  fi
fi
echo $$ > $PIDFILE

trap 'rm -f "$PIDFILE" >/dev/null 2>&1' EXIT HUP KILL INT QUIT TERM

# do the work


1
2017-11-09 14:33



Teşekkürler, örnek yararlıdır - Eğer zaten çalışıyorsa komut dosyasının çıkmasını istiyorum. Bahsettiğin için teşekkürler ickdo - Bu hile yapmak gibi görünüyor. - Tom


Önceki örneklerin hala çalışıyorsa, cron daemon'unuz işe girmemelidir. Ben bir cron daemon geliştiricisi dcronve özellikle bunu engellemeye çalışırız. Vixie cron ya da diğer daemonların bunu nasıl halledeceğini bilmiyorum.


1
2018-02-17 15:59





Kullanmanı tavsiye ederim çalışma birini Komut - kilitlerle uğraşmaktan çok daha basit. Dokümanlardan:

çalışma birini benzersiz bir argüman kümesiyle bazı komutların birden çok benzersiz örneğini çalıştıran bir sarmalayıcı betiğidir. Bir kerede birden fazla kopya çalışmasını istediğinizde, bu genellikle cronjobs ile yararlıdır.

çalışma bu-one tam olarak run-one gibi, kullanıcı tarafından sahip olunan herhangi bir çalışan işlemi bulmak ve öldürmek için pgrep kullanacak ve öldürecektir. ve hedef komutları ve argümanları eşleştirerek. Tüm eşleşene kadar, eşleşen süreçleri öldürmeye çalışırken, bu-run-one'ın engelleneceğini unutmayın. süreçler öldü.

çalışma birini-sürekli tam olarak çalışır gibi çalışır COMMAND (sıfır veya sıfır olmayan) çıktığı zaman "COMMAND [ARGS]" ifadesini yeniden gönderir.

keep-birini süren run-one-sürekli bir takma addır.

çalışma birini-dek-başarı tam olarak çalışır durumda-bir-sürekli olarak çalışır COMMAND başarılı bir şekilde çıkana kadar "COMMAND [ARGS]" i yeniden paylaşıyor (örneğin, sıfırdan çıkar).

çalışma birini-dek-başarısızlık tam olarak çalışır durumda-bir-sürekli olarak çalışır COMMAND başarısızlıkla çıkana kadar "COMMAND [ARGS]" i yeniden paylaşıyor (örn. sıfırdan çıkar).


1
2017-10-02 21:53





Çoğalmış crons gibi java veya kabuk cron olabilir gibi bu sorunu çözmek için bir kavanoz oluşturduk. Duplicates.CloseSessions ("Demo.jar") 'da cron adını geçmeniz yeterlidir. Bu, akım haricinde bu cron için varolan pid'i arayacak ve öldürecektir. Bunu yapmak için yöntem uyguladım. String proname = ManagementFactory.getRuntimeMXBean (). GetName ();                 String pid = proname.split ("@") [0];                 System.out.println ("Geçerli PID:" + pid);

            Process proc = Runtime.getRuntime().exec(new String[]{"bash","-c"," ps aux | grep "+cronname+" | awk '{print $2}' "});

            BufferedReader stdInput = new BufferedReader(new InputStreamReader(proc.getInputStream()));
            String s = null;
            String killid="";

            while ((s = stdInput.readLine()) != null ) {                                        
                if(s.equals(pid)==false)
                {
                    killid=killid+s+" ";    
                }
            }

Ve sonra tekrar killid dizesini tekrar shell komutuyla öldür.


0
2017-12-28 08:36



Bunun gerçekten soruya cevap verdiğini düşünmüyorum. - kasperd