Başka bir kabukta başlayan bir programda nasıl beklerim


20

Çalıştığı tüm veriler kullanılabilir olduğunda cron tarafından başlatılan büyük miktarda çalışma (yaklaşık 4-5 saat sürer) yapan bir programım var. Bazen, bitmesini beklediğimde, bittiğinde başka bir (etkileşimli) programın başlatılmasını isterdim. bekleme çağrısı umut verici görünüyor ama sadece çocuklar için bekleyecek.


Anlayabildiğim diğer tek yöntem, cronjob'dan bir dosya oluşturmak ve daha sonra bu işlemde inotifywait kullanmaktır, dosyalar silindiğinde 2. işleminiz (inotifywait çalışıyor) başlayabilir.
slm

ipcSüreçler arası iletişimi kullanarak da bu çizgiler boyunca bir şeyler yapabileceğinizi düşünüyorum . man ipc.
slm

Yeniden başlatmak için bir hizmet izlemeseniz de, Tanrı, Monit veya bu soru-cevap bölümünde belirtilen diğer pkgslerden biri
slm

@slm herhangi bir dosya sisteminde kullanılabilir inotify örneğin / proc / _pid_ / fd / 1 üzerinde close_write bekle?
Hildred

Tamamen emin değilim, ama bunu yapmanın başka bir yolu olabilir 8-). Inotifywait'e (dosyalar için) benzer süreç izleme ile ilgili bazı yeni çekirdek işlevlerinin nerede olduğunu hatırladığım bazı Q'lar vardı. Bu yeni özellik süreçteki olaylar içindi, diye düşündüm, ancak soru-cevap birçoğu aklımda birlikte çalışmaya başladı 8-). Bence A benim ya da Gilles tarafından sağlanmıştı.
slm

Yanıtlar:


13

I Kesinlikle EDIT # 3 çözümünü tercih edin (aşağıya bakınız).

aynı kabuk içinde değilse ps-p doğru koşulu ile bir while döngüsü kullanın . İşlemci kullanımını azaltmak için döngüye bir uyku koyun .

while ps -p <pid> >/dev/null 2>&1
do
   sleep 10
done 

veya UNIX'iniz / proc destekliyorsa (örneğin HP-UX hala desteklemiyorsa).

while [[ -d /proc/<pid> ]]
do 
    sleep 10
done

Zaman aşımı istiyorsanız

timeout=6  # timeout after 1mn  
while ((timeout > 0)) && ps -p <pid> >/dev/null 2>&1
do
   sleep 10
   ((timeout -= 1))
done 

DÜZENLEME # 1

Başka bir yol var: cron kullanma . İşlerinizi yığınlamak için toplu iş komutunu kullanın .

Örneğin günlük olarak tüm işlerinizi istifleyebilirsiniz. Toplu işlem bazı paralelliğe izin verecek şekilde ayarlanabilir, böylece engellenen bir iş tüm yığını durdurmaz (İşletim sistemine bağlıdır).

DÜZENLEME # 2

Ana dizininizde bir fifo oluşturun:

$ mkfifo ~/tata

işinizin sonunda:

echo "it's done" > ~/tata

diğer işin başlangıcında (bekleyen kişi):

cat ~/tata 

Yoklama değil eski iyi engelleme IO.

EDIT # 3

Sinyalleri kullanma:

Bekliyor kim (ler) başında:

echo $$ >>~/WeAreStopped
kill -STOP $$

uzun işinizin sonunda:

if [[ -f ~/WeAreStopped ]] ; then
    xargs kill -CONT < ~/WeAreStopped
    rm ~/WeAreStopped
fi

Yoklama, yuck! Güzel karar: işlemci zamanını ya da uykuyu ayarlamak için zamanımı boşa harcıyorum. Daha iyi bir cevap olmalı.
Hildred

:) Yoklama sizin için iyidir, yoklama durumsuzdur, yoklama güvenilirdir.
Emmanuel

yoklama yavaştır, kutuplama işlemci süresini boşa harcar.
Hildred

0.01s yürütme süresi ile 4 saat boyunca yürütülen 1440 ps 14.4s tüketirdi. İş bağımlılıklarını yöneten bir zamanlayıcıdan çok daha az: D
Emmanuel

Bunun muhtemelen en iyi seçenek olduğunu düşünüyorum: stackoverflow.com/questions/1058047/… , hacky olmasına rağmen.
slm

5

Bazı bayrak kullanmak için cron işinizi değiştirebilirsiniz.

Onun yerine

2  2 * * *           /path/my_binary

Kullanabilirsiniz

2  2 * * *           touch /tmp/i_m_running; /path/my_binary; rm /tmp/i_m_running

Ve sadece bu dosyayı komut dosyasında veya hatta elle izleyin. Varsa, programınız çalışıyor demektir; Aksi takdirde ne isterseniz yapabilirsiniz.

Senaryo örneği:

while [[ -f /tmp/i_m_running ]] ; do
   sleep 10 ;
done
launch_whatever_you_want

Kullanmak istemiyorsanız sleep, komut dosyasını değiştirebilir ve her X dakikada bir cron üzerinden çalıştırabilirsiniz.

Bu durumda komut dosyası örneği şöyle olur:

[[ -f /tmp/i_m_running ]] && { echo "Too early" ; exit ; }
launch_whatever_you_want

Bu şekilde biraz daha kolaydır, çünkü cron işleminizin PID'sini bulmak zorunda değilsiniz.


4

Bir ebeveynin alt süreçlerinden birinin bitmesini beklemesi dışında, bir sürecin başka bir sürecin bitmesini bekleyeceği bir tesis yoktur. Yapabiliyorsanız, programı bir komut dosyası aracılığıyla başlatın:

do_large_amount_of_work
start_interactive_program

Bunu yapamıyorsanız, örneğin büyük miktarda işi bir cron işinden, ancak etkileşimli programı oturumunuzun bağlamından başlatmak istemeden önce, bunu yapın

do_large_amount_of_work
notify_completion

Uygulamanın birkaç yolu vardır notify_completion. Bazı masaüstü ortamları bildirim mekanizması (sağlamak Aç bir uzak X ekranda bir pencere (neden?) "Açık ekran Can not" yararlı olabilir). Dosya değişikliği bildirimlerini kullanarak da bir tane yapabilirsiniz. Linux'ta, dosya değişikliği bildirim özelliği inotify .

do_large_amount_of_work
echo $? >/path/to/finished.stamp

Şunun yaratılmasına tepki vermek için /path/to/finished.stamp:

inotifywait -e close_write -q /path/to/finished.stamp
start_interactive_program

do_large_amount_of_workÇağrılan yolu değiştiremezseniz , ancak en son hangi dosyayı değiştirdiğini biliyorsanız, bu dosya kapatıldığında tepki vermek için aynı mekanizmayı kullanabilirsiniz. Bir dosyanın yeniden adlandırılması gibi diğer olaylara da yanıt verebilirsiniz (bkz.inotifywait (olasılıkların listesi kılavuza ).


0

Komut dosyasının cronjob tarafından tetiklenmesini sağlayın, içine ihtiyacınız varsa takip görevleri ekleyebileceğiniz boş bir kabuk komut dosyası çağırın.

Gilles'in yaklaşımına çok benzer.

cronjob-task.sh içerir:

# do_large_amount_of_work

./post-execute.sh

nerede post-execute.shsen bir takip görevi tetiklemek gerektiğini görmedikçe genellikle boş olduğunu.

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.