Contoh Anda dan jawaban yang diterima terlalu rumit, mengapa Anda tidak hanya gunakan timeout
karena itu persis kasus penggunaannya? timeout
perintah bahkan memiliki opsi bawaan (-k
) untuk mengirim SIGKILL
setelah mengirimkan sinyal awal untuk mengakhiri perintah (SIGTERM
secara default) jika perintah masih berjalan setelah mengirimkan sinyal awal (lihat man timeout
).
Jika skrip tidak perlu wait
dan melanjutkan alur kontrol setelah menunggu, itu hanya masalah
timeout -k 60s 60s app1 &
timeout -k 60s 60s app2 &
# [...]
Namun, jika ya, itu sama mudahnya dengan menyimpan timeout
PID sebagai gantinya:
pids=()
timeout -k 60s 60s app1 &
pids+=($!)
timeout -k 60s 60s app2 &
pids+=($!)
wait "${pids[@]}"
# [...]
Mis.
$ cat t.sh
#!/bin/bash
echo "$(date +%H:%M:%S): start"
pids=()
timeout 10 bash -c 'sleep 5; echo "$(date +%H:%M:%S): job 1 terminated successfully"' &
pids+=($!)
timeout 2 bash -c 'sleep 5; echo "$(date +%H:%M:%S): job 2 terminated successfully"' &
pids+=($!)
wait "${pids[@]}"
echo "$(date +%H:%M:%S): done waiting. both jobs terminated on their own or via timeout; resuming script"
.
$ ./t.sh
08:59:42: start
08:59:47: job 1 terminated successfully
08:59:47: done waiting. both jobs terminated on their own or via timeout; resuming script
Tulis PID ke file dan jalankan aplikasi seperti ini:
pidFile=...
( app ; rm $pidFile ; ) &
pid=$!
echo $pid > $pidFile
( sleep 60 ; if [[ -e $pidFile ]]; then killChildrenOf $pid ; fi ; ) &
killerPid=$!
wait $pid
kill $killerPid
Itu akan membuat proses lain yang tidur selama waktu tunggu dan mematikan proses jika belum selesai sejauh ini.
Jika proses selesai lebih cepat, file PID dihapus dan proses pembunuh dihentikan.
killChildrenOf
adalah skrip yang mengambil semua proses dan mematikan semua turunan dari PID tertentu. Lihat jawaban pertanyaan ini untuk berbagai cara mengimplementasikan fungsi ini:Cara terbaik untuk menghentikan semua proses anak
Jika Anda ingin keluar dari BASH, Anda dapat menulis PID dan batas waktu ke direktori dan menonton direktori itu. Setiap menit atau lebih, baca entri dan periksa proses mana yang masih berjalan dan apakah waktunya habis.
EDIT Jika Anda ingin mengetahui apakah proses telah berhasil mati, Anda dapat menggunakan kill -0 $pid
EDIT2 Atau Anda dapat mencoba memproses grup. kevinarpe berkata:Untuk mendapatkan PGID untuk PID(146322):
ps -fjww -p 146322 | tail -n 1 | awk '{ print $4 }'
Dalam kasus saya:145974. Kemudian PGID dapat digunakan dengan opsi khusus kill untuk menghentikan semua proses dalam grup:kill -- -145974