Cara mendapatkan daftar semua proses anak yang dihasilkan oleh skrip

9

Konteks:

Pengguna memberi saya skrip khusus untuk dijalankan. Skrip ini dapat berupa skrip apa saja untuk memulai beberapa program GUI, layanan backend. Saya tidak memiliki kendali atas bagaimana skrip ditulis. Script ini bisa dari jenis pemblokiran yaitu eksekusi menunggu sampai semua proses anak (program yang dijalankan secara berurutan) keluar

#exaple of blocking script
echo "START"
first_program 
second_program 
echo "DONE"

atau tipe non blocking yaitu yang memproses anak di latar belakang dan keluar seperti

#example of non-blocking script
echo "START"
first_program &
second_program &
echo "DONE"

Apa yang saya coba capai?

Skrip yang disediakan pengguna dapat berupa salah satu dari dua jenis di atas atau campuran keduanya. Pekerjaan saya adalah menjalankan skrip dan menunggu sampai semua proses dimulai dengan itu keluar dan kemudian mematikan node. Jika jenis pemblokirannya, case sederhana saja yaitu mendapatkan PID dari proses eksekusi skrip dan menunggu hingga ps -ef | grep -ef PID tidak memiliki entri lagi. Script yang tidak menghalangi adalah yang membuat saya kesulitan

Apakah ada cara saya bisa mendapatkan daftar PID dari semua proses anak yang dihasilkan oleh eksekusi skrip? Setiap petunjuk atau petunjuk akan sangat dihargai

irraju
sumber
Saya tidak berpikir itu mungkin setelah skrip induk berakhir kecuali Anda dapat menangkap PID induknya. Jika Anda meluncurkan skrip, Anda bisa membungkusnya dengan sesuatu seperti pid$(foo.sh; echo $!)yang akan memberi Anda PID foo.shsehingga Anda dapat menggunakannya ps --ppid. Apakah itu akan berhasil?
terdon
2
Apakah skrip harus dijalankan di bawah UID pengguna penulis? Jika tidak, bisakah Anda membuat pengguna tiruan hanya untuk tujuan ini? Anda bahkan tidak perlu grep, hanya ps –udummy_user. Juga, lihat kelompok proses.
Scott
Ini lebih merupakan jenis solusi daripada solusi untuk pertanyaan awal Anda: Buka sesi bash baru. Anda dapat membuat daftar semua proses yang muncul dari shell ini menggunakan pstanpa argumen (harus hanya bashdan psdi awal). Mulai skrip Anda di sana. Setelah selesai, tunggu hingga ps | wc -lmencapai nilai yang Anda harapkan.
Tim

Jawaban:

8

Untuk menjawab pertanyaan Anda secara langsung, perintah

jobs -p

memberi Anda daftar semua proses anak.

Alternatif # 1

Tetapi dalam kasus Anda, mungkin lebih mudah menggunakan perintah waittanpa params:

first_program &
second_program &
wait

Ini akan menunggu sampai SEMUA proses anak selesai.

Alternatif # 2

Alternatif lain adalah menggunakan $!untuk mendapatkan PID dari program terakhir dan mungkin terakumulasi dalam variabel, seperti:

pids=""
first_program &
pids="$pids $!"
second_program &
pids="$pids $!"

dan kemudian gunakan tunggu dengan itu (ini dalam kasus Anda hanya ingin menunggu subset dari proses anak Anda):

wait $pids

Alternatif # 3

ATAU, jika Anda hanya ingin menunggu sampai proses APA SAJA selesai, Anda dapat menggunakannya

wait -n $pids

Info bonus

Jika Anda ingin sigterm ke skrip bash Anda untuk menutup proses anak Anda juga, Anda perlu menyebarkan sinyal dengan sesuatu seperti ini (letakkan ini di bagian atas, sebelum memulai proses apa pun):

trap 'kill $(jobs -p)' SIGINT SIGTERM EXIT
Vlad A Ionescu
sumber
1

Terima kasih teman-teman atas tanggapan Anda .. Saya mendapat solusi di stackoverflow

Anda dapat menggunakan menunggu untuk menunggu semua proses latar belakang yang dimulai oleh skrip pengguna untuk menyelesaikan. Karena menunggu hanya berfungsi pada anak-anak dari shell saat ini, Anda harus mengambil skrip mereka alih-alih menjalankannya sebagai proses terpisah.

(sumber skrip pengguna; tunggu)

Sumber skrip dalam subkulit eksplisit harus mensimulasikan memulai proses baru cukup dekat. Jika tidak, Anda juga bisa latar belakang subkulit, yang memaksa proses baru untuk dimulai, kemudian tunggu sampai selesai.

(sumber skrip pengguna; tunggu) & tunggu

Berikut adalah tautan untuk jawaban asli oleh @chepner: /programming/18663196/how-to-get-list-of-all-child-process-spawned-by-a-script/18663969?noredirect = 1 # 18663969

irraju
sumber
3
Saya memikirkan hal ini juga, tetapi solusi ini gagal ketika userscript memulai subscript di latar belakang yang kemudian memulai skrip lain di latar belakang. waitPerintah Anda kemudian akan menunggu anak-anak userscript tetapi tidak untuk cucunya.
Tim
@Tim Baru sadar bahwa :(
irraju