Apakah ada fitur bawaan di Bash untuk menunggu proses selesai?
Itu wait
perintah saja memungkinkan seseorang untuk menunggu proses anak sampai akhir. Saya ingin tahu apakah ada cara untuk menunggu proses selesai sebelum melanjutkan dalam skrip apa pun.
Cara mekanis untuk melakukan ini adalah sebagai berikut, tetapi saya ingin tahu apakah ada fitur builtin di Bash.
while ps -p `cat $PID_FILE` > /dev/null; do sleep 1; done
Jawaban:
Untuk menunggu proses apa pun selesai
Linux:
Darwin (mengharuskan yang
$pid
memiliki file terbuka):Dengan batas waktu (detik)
Linux:
Darwin (mengharuskan yang
$pid
memiliki file terbuka):sumber
tail
akan melakukan ini.tail
bekerja di bawah tenda dengan pemungutan suarakill(pid, SIG_0)
untuk suatu proses (ditemukan menggunakanstrace
).+r 1
batas waktu, saya pribadi mencari solusi untuk MacOS yang tidak menggunakan polling.tail
memiliki gariskill (pid, 0) != 0 && errno != EPERM
.caffeinate -w $pid
akan melakukan trik.Tidak ada builtin. Gunakan
kill -0
dalam satu lingkaran untuk solusi yang bisa diterapkan:Atau sebagai oneliner sederhana untuk penggunaan satu kali mudah:
Seperti dicatat oleh beberapa komentator, jika Anda ingin menunggu proses yang Anda tidak memiliki hak untuk mengirim sinyal, Anda telah menemukan beberapa cara lain untuk mendeteksi jika proses sedang berjalan untuk mengganti
kill -0 $pid
panggilan. Di Linux,test -d "/proc/$pid"
berfungsi, di sistem lain Anda mungkin harus menggunakanpgrep
(jika tersedia) atau sesuatu sepertips | grep "^$pid "
.sumber
sleep 0.5
, proses dengan$pid
mungkin mati dan proses lain dapat dibuat dengan hal yang sama$pid
. Dan kita akan berakhir menunggu 2 proses berbeda (atau bahkan lebih) dengan yang sama$pid
.Saya menemukan "kill -0" tidak berfungsi jika prosesnya dimiliki oleh root (atau lainnya), jadi saya menggunakan pgrep dan menghasilkan:
Ini akan memiliki kerugian dari proses zombie yang mungkin cocok.
sumber
kill(pid, sig=0)
gagal jika proses pemanggil tidak memiliki hak istimewa untuk mematikan. Jadi / bin / kill -0 dan "kill -0" (bash built-in) gagal juga dalam kondisi yang sama.Loop skrip bash ini berakhir jika prosesnya tidak ada, atau zombie.
EDIT : Skrip di atas diberikan di bawah ini oleh Rockallite . Terima kasih!
Jawaban orignal saya di bawah berfungsi untuk Linux, dengan mengandalkan
procfs
mis/proc/
. Saya tidak tahu portabilitasnya:Ini tidak terbatas pada shell, tetapi OS itu sendiri tidak memiliki panggilan sistem untuk menonton pemutusan proses non-anak.
sumber
grep /proc/$PID/status
dengan tanda kutip ganda (bash: test: argument expected
)while s=`ps -p $PID -o s=` && [[ "$s" && "$s" != 'Z' ]]; do sleep 1; done
ps
, tidak ada-p
ataus=
didukungFreeBSD dan Solaris memiliki ini berguna
pwait(1)
utilitas , yang tidak sesuai dengan yang Anda inginkan.Saya percaya, OS modern lainnya juga memiliki panggilan sistem yang diperlukan (MacOS, misalnya, mengimplementasikan BSD
kqueue
), tetapi tidak semua membuatnya tersedia dari command-line.sumber
> BSD and Solaris
: Memeriksa tiga BSD besar yang muncul di pikiran; baik OpenBSD maupun NetBSD tidak memiliki fungsi ini (di halaman manualnya), hanya FreeBSD yang berfungsi, karena Anda dapat dengan mudah memeriksa man.openbsd.org .kqueue
, jadi mengkompilasi FreeBSDpwait(1)
akan sepele. Mengapa BSD yang lain tidak mengimpor fitur itu luput dari saya ...plink me@oracle box -pw redacted "pwait 6998";email -b -s "It's done" etc
biarkan aku pulang sekarang, bukan berjam-jam dari sekarang.Dari halaman bash
sumber
wait
tanpa args akan memblokir proses sampai proses anak selesai. Sejujurnya, saya tidak melihat gunanya menunggu proses apa pun karena selalu ada proses yang terjadi.sleep 1000
ctrl-z
wait [sleep pid]
segera kembaliSemua solusi ini diuji di Ubuntu 14.04:
Solusi 1 (dengan menggunakan perintah ps): Hanya untuk menambahkan hingga jawaban Pierz, saya akan menyarankan:
Dalam hal ini,
grep -vw grep
pastikan bahwa grep hanya cocok dengan process_name dan bukan grep itu sendiri. Ini memiliki keuntungan mendukung kasus-kasus di mana process_name tidak di akhir baris dips axg
.Solusi 2 (dengan menggunakan perintah teratas dan nama proses):
Ganti
process_name
dengan nama proses yang muncul ditop -n 1 -b
. Harap simpan tanda kutip.Untuk melihat daftar proses yang Anda tunggu sampai selesai, Anda dapat menjalankan:
Solusi 3 (dengan menggunakan perintah teratas dan ID proses):
Ganti
process_id
dengan ID proses program Anda.sumber
grep -v grep
pipa panjang adalah antipattern yang besar, dan ini mengandaikan bahwa Anda tidak memiliki proses yang tidak terkait dengan nama yang sama. Jika Anda tahu PID sebagai gantinya, ini bisa disesuaikan dengan solusi yang berfungsi dengan baik.-w
untuk menghindari masalahgrep -v grep
sampai batas tertentu . Saya juga menambahkan dua solusi lagi berdasarkan komentar Anda.Oke, jadi sepertinya jawabannya adalah - tidak, tidak ada alat bawaan.
Setelah diatur
/proc/sys/kernel/yama/ptrace_scope
ke0
, dimungkinkan untuk menggunakanstrace
program. Switch lebih lanjut dapat digunakan untuk membuatnya diam, sehingga benar-benar menunggu secara pasif:sumber
Operation not permitted
untuk contoh strace kedua); dapatkah kamu mengkonfirmasi itu?(...)"tracee" always means "(one) thread"
(dan saya mengkonfirmasi kesalahan yang Anda sebutkan). Untuk membiarkan lebih banyak proses menunggu dengan cara ini, Anda harus membuat rantai.Solusi pemblokiran
Gunakan
wait
dalam satu lingkaran, untuk menunggu mengakhiri semua proses:Fungsi ini akan segera keluar, ketika semua proses dihentikan. Ini adalah solusi paling efisien.
Solusi non-pemblokiran
Gunakan
kill -0
dalam satu lingkaran, untuk menunggu penghentian semua proses + lakukan apa saja di antara pemeriksaan:Waktu reaksi menurun ke
sleep
waktu, karena harus mencegah penggunaan CPU yang tinggi.Penggunaan yang realistis:
Menunggu untuk mengakhiri semua proses + memberi tahu pengguna tentang semua PID yang sedang berjalan.
Catatan
Fungsi-fungsi ini mendapatkan PID melalui argumen oleh
$@
sebagai BASH array.sumber
Punya masalah yang sama, saya memecahkan masalah mematikan proses dan kemudian menunggu setiap proses selesai menggunakan sistem file PROC:
sumber
Tidak ada fitur builtin untuk menunggu proses selesai.
Anda dapat mengirim
kill -0
ke PID yang ditemukan, sehingga Anda tidak bingung dengan zombie dan hal-hal yang masih akan terlihat dips
(sambil tetap mengambil daftar PID menggunakanps
).sumber
Gunakan inotifywait untuk memantau beberapa file yang ditutup, saat proses Anda berakhir. Contoh (di Linux):
-e menentukan acara yang akan ditunggu, -q berarti output minimal hanya pada penghentian. Dalam hal ini adalah:
Perintah tunggu tunggal dapat digunakan untuk menunggu beberapa proses:
String keluaran inotifywait akan memberi tahu Anda, proses mana yang dihentikan. Ini hanya berfungsi dengan file 'asli', bukan dengan sesuatu di / proc /
sumber
Pada sistem seperti OSX Anda mungkin tidak memiliki pgrep sehingga Anda dapat mencoba appraoch ini, ketika mencari proses dengan nama:
The
$
simbol pada akhir memastikan nama proses yang pertandingan grep hanya process_name ke akhir baris dalam output ps dan tidak sendiri.sumber
/dev/null
,-q
harus digunakan dengangrep
. Contoh lain dari proses ini mungkin telah dimulai ketika lingkaran Anda sedang tidur dan Anda tidak akan pernah tahu ...-q
saran tersebut valid, seperti yang saya sebutkan dalam jawaban saya secara khusus,$
berarti mengakhiri grep tidak akan cocok dengan nama "di suatu tempat di baris perintah" juga tidak akan cocok dengan dirinya sendiri. Sudahkah Anda mencobanya di OSX?Solusi Rauno Palosaari untuk
Timeout in Seconds
Darwin
, adalah solusi yang sangat baik untuk OS mirip UNIX yang tidak memiliki GNUtail
(tidak spesifik untukDarwin
). Tetapi, tergantung pada usia sistem operasi mirip UNIX, baris perintah yang ditawarkan lebih kompleks daripada yang diperlukan, dan dapat gagal:Pada setidaknya satu UNIX lama,
lsof
argumen+r 1m%s
gagal (bahkan untuk pengguna super):Ini
m%s
adalah spesifikasi format keluaran. Post-prosesor yang lebih sederhana tidak memerlukannya. Misalnya, perintah berikut menunggu PID 5959 hingga lima detik:Dalam contoh ini, jika PID 5959 keluar dengan sendirinya sebelum lima detik berlalu,
${?}
adalah0
. Jika tidak${?}
kembali1
setelah lima detik.Mungkin perlu secara khusus mencatat bahwa dalam
+r 1
,1
ini adalah interval jajak pendapat (dalam detik), sehingga dapat diubah agar sesuai dengan situasi.sumber