Bagaimana saya menunggu program dimulai di shell lain

20

Saya memiliki program yang melakukan banyak pekerjaan (membutuhkan sekitar 4-5 jam) yang dimulai oleh cron ketika semua data yang digunakannya tersedia. Kadang-kadang, ketika saya menunggu sampai selesai, saya ingin dapat memulai (interaktif) program lain ketika selesai. panggilan tunggu terlihat menjanjikan tetapi hanya akan menunggu anak-anak.

Hildred
sumber
Satu-satunya metode lain yang dapat saya bayangkan adalah membuat file dari cronjob, dan kemudian menggunakan inotifywait pada proses itu, ketika file dihapus, proses ke-2 Anda (menjalankan inotifywait) dapat dimulai.
slm
Saya pikir Anda bisa melakukan sesuatu dengan menggunakan ipckomunikasi interprocess. man ipc.
slm
Meskipun Anda tidak melihat layanan untuk memulai kembali, Tuhan, Monit, atau salah satu pkg lain yang disebutkan dalam T&J ini akan melakukan pekerjaan itu juga: unix.stackexchange.com/questions/75785/…
slm
@slm dapat membatalkan penggunaan pada sistem file apa saja misalnya menunggu close_write di / proc / _pid_ / fd / 1?
Hildred
Tidak sepenuhnya yakin, tapi itu mungkin cara lain untuk melakukannya 8-). Ada beberapa Q yang saya ingat di mana ada beberapa fungsionalitas kernel baru yang terkait dengan proses pemantauan mirip dengan inotifywait (untuk file). Fitur baru ini untuk acara yang sedang dalam proses, saya pikir tetapi banyak dari Q&A mulai berjalan bersama dalam pikiran saya 8-). Saya pikir A disediakan oleh saya atau Gilles.
slm

Jawaban:

13

Saya lebih suka solusi EDIT # 3 (lihat di bawah).

jika tidak dalam shell yang sama, gunakan loop sementara dengan kondisi pada ps -p mengembalikan true. Letakkan tidur di loop untuk mengurangi penggunaan prosesor.

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

atau jika UNIX Anda mendukung / proc (misalnya HP-UX masih tidak).

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

Jika Anda ingin batas waktu

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

EDIT # 1

Ada cara lain: jangan gunakan cron . Gunakan perintah batch untuk menumpuk pekerjaan Anda.

Misalnya Anda bisa setiap hari menumpuk semua pekerjaan Anda. Batch dapat disetel untuk memungkinkan beberapa paralelisme sehingga pekerjaan yang diblokir tidak akan menghentikan semua tumpukan (Itu tergantung pada sistem operasi).

EDIT # 2

Buat fifo di direktori home Anda:

$ mkfifo ~/tata

di akhir pekerjaan Anda:

echo "it's done" > ~/tata

di awal pekerjaan lain (orang yang menunggu):

cat ~/tata 

Ini bukan polling, itu sudah lama memblokir IO.

EDIT # 3

Menggunakan sinyal:

Di awal skrip, siapa yang menunggu:

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

di akhir pekerjaan panjang Anda:

if [[ -f ~/WeAreStopped ]] ; then
    xargs kill -CONT < ~/WeAreStopped
    rm ~/WeAreStopped
fi
Emmanuel
sumber
Polling, huh! Keputusan yang indah: buang waktu prosesor atau waktu saya untuk menyetel tidur. Harus ada jawaban yang lebih baik.
Hildred
:) Polling itu baik untuk Anda, polling itu stateless, polling itu bisa diandalkan.
Emmanuel
polling lambat, poling menyia-nyiakan waktu prosesor.
Hildred
Dengan waktu eksekutif 0,01 1440 ps dieksekusi selama 4 jam akan mengkonsumsi 14,4 detik. Jauh lebih sedikit daripada scheduler yang mengelola dependensi pekerjaan: D
Emmanuel
Saya pikir ini kemungkinan merupakan pilihan terbaik: stackoverflow.com/questions/1058047/… , meskipun ini merupakan peretasan.
slm
5

Anda dapat memodifikasi pekerjaan cron Anda untuk menggunakan beberapa flag.

Dari pada

2  2 * * *           /path/my_binary

Anda dapat gunakan

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

Dan pantau saja file ini dalam skrip atau bahkan secara manual. Jika ada, maka program Anda sedang berjalan; jika tidak merasa bebas untuk melakukan apa pun yang Anda inginkan.

Sampel skrip:

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

Jika Anda tidak suka menggunakan sleep, Anda dapat memodifikasi skrip dan menjalankannya melalui cron sekali per X menit.

Dalam hal contoh skrip akan:

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

Cara ini sedikit lebih mudah, karena Anda tidak harus menemukan PID dari proses cron Anda.

buru-buru
sumber
4

Tidak ada fasilitas untuk proses untuk menunggu proses lain selesai, kecuali untuk orang tua menunggu salah satu proses anaknya selesai. Jika bisa, luncurkan program melalui skrip:

do_large_amount_of_work
start_interactive_program

Jika Anda tidak dapat melakukan itu, misalnya sebelum Anda ingin memulai sejumlah besar pekerjaan dari cron job tetapi program interaktif dari konteks sesi Anda, maka buat ini

do_large_amount_of_work
notify_completion

Ada beberapa cara untuk mengimplementasikannya notify_completion. Beberapa lingkungan desktop menyediakan mekanisme pemberitahuan ( Buka jendela pada tampilan X jarak jauh (mengapa "Tidak dapat membuka layar")? Mungkin bermanfaat). Anda juga dapat membuatnya menggunakan pemberitahuan perubahan file. Di Linux, fasilitas pemberitahuan perubahan file tidak valid .

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

Untuk bereaksi terhadap penciptaan /path/to/finished.stamp:

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

Jika Anda tidak dapat mengubah cara do_large_amount_of_workdipanggil, tetapi Anda tahu file apa yang dimodifikasi terakhir, Anda dapat menggunakan mekanisme yang sama untuk bereaksi ketika file itu ditutup. Anda juga dapat bereaksi terhadap peristiwa lain seperti penggantian nama file (lihat inotifywaitmanual untuk daftar kemungkinan).

Gilles 'SANGAT berhenti menjadi jahat'
sumber
0

Biarkan skrip dipicu oleh cronjob untuk memanggil skrip shell kosong tempat Anda dapat memasukkan tugas tindak lanjut jika Anda membutuhkannya.

Ini sangat mirip dengan pendekatan Gilles.

cronjob-task.sh mengandung:

# do_large_amount_of_work

./post-execute.sh

di mana post-execute.shbiasanya kosong, kecuali Anda melihat bahwa Anda perlu memicu tugas tindak lanjut.

Daniel F
sumber