Katakanlah kita memiliki skrip bash seperti:
echo "x" &
echo "y" &
echo "z" &
.....
echo "Z" &
wait
apakah ada cara untuk mengumpulkan kode keluar dari subkulit / proses sub? Mencari cara untuk melakukan ini dan tidak dapat menemukan apa pun. Saya perlu menjalankan subshell ini secara paralel, jika tidak ya ini akan lebih mudah.
Saya mencari solusi generik (Saya memiliki sejumlah proses sub yang tidak diketahui / dinamis untuk dijalankan secara paralel).
bash
shell-script
shell
subshell
Alexander Mills
sumber
sumber
Jawaban:
Jawaban oleh Alexander Mills yang menggunakan handleJobs memberi saya titik awal yang bagus, tetapi juga memberi saya kesalahan ini
Yang mungkin merupakan masalah kondisi ras bash
Sebaliknya saya hanya menyimpan pid dari setiap anak dan menunggu dan mendapatkan kode keluar untuk setiap anak secara khusus. Saya menemukan pembersih ini dalam hal subproses pemijahan subproses dalam fungsi dan menghindari risiko menunggu proses induk di mana saya dimaksudkan untuk menunggu anak. Lebih jelas apa yang terjadi karena tidak menggunakan jebakan.
sumber
for job in "${childen[@]}"; do
seharusnya begitufor job in "${1}"; do
, untuk kejelasanchildren_pids+=("$!")
benar-benar menangkap pid yang diinginkan untuk sub shell.Gunakan
wait
dengan PID, yang akan:Anda harus menyimpan PID dari setiap proses saat berjalan:
Anda juga dapat mengaktifkan kontrol pekerjaan dalam skrip dengan
set -m
dan menggunakan%n
jobspec, tetapi Anda hampir pasti tidak mau - kontrol pekerjaan memiliki banyak efek samping lainnya .wait
akan mengembalikan kode yang sama saat proses selesai. Anda dapat menggunakanwait $X
kapan saja (masuk akal) nanti untuk mengakses kode akhir$?
atau hanya menggunakannya sebagai benar / salah:wait
akan berhenti sampai perintah selesai jika belum.Jika Anda ingin menghindari kemacetan seperti itu, Anda dapat mengatur a
trap
padaSIGCHLD
, menghitung jumlah terminasi, dan menangani semuawait
s sekaligus ketika mereka sudah semua selesai. Anda mungkin bisa lolos menggunakanwait
sendiri hampir sepanjang waktu.sumber
wait $X
pada titik mana pun (masuk akal) nanti.Jika Anda memiliki cara yang baik untuk mengidentifikasi perintah, Anda dapat mencetak kode keluarnya ke file tmp dan kemudian mengakses file tertentu yang Anda minati:
Jangan lupa untuk menghapus file tmp.
sumber
Gunakan a
compound command
- masukkan pernyataan dalam tanda kurung:akan memberikan output
Cara yang sangat berbeda untuk menjalankan beberapa perintah secara paralel adalah dengan menggunakan GNU Parallel . Buat daftar perintah untuk dijalankan dan letakkan di file
list
:Jalankan semua perintah secara paralel dan kumpulkan kode keluar di file
job.log
:dan hasilnya adalah:
sumber
PIPESTATUS
adalah sesuatu yang harus Anda periksa. Iniseq 10 | gzip -c > seq.gz ; echo ${PIPESTATUS[@]}
kembali0 0
(kode keluar dari perintah pertama dan terakhir).ini skrip generik yang Anda cari. Satu-satunya downside adalah perintah Anda dalam tanda kutip yang berarti penyorotan sintaks melalui IDE Anda tidak akan benar-benar berfungsi. Kalau tidak, saya sudah mencoba beberapa jawaban lain dan ini adalah yang terbaik. Jawaban ini menggabungkan ide menggunakan yang
wait <pid>
diberikan oleh @Michael tetapi melangkah lebih jauh dengan menggunakantrap
perintah yang tampaknya bekerja paling baik.terima kasih kepada @michael homer karena membawa saya ke jalur yang benar, tetapi menggunakan
trap
perintah adalah pendekatan terbaik AFAICT.sumber
Variasi lain dari jawaban @rolf:
Cara lain untuk menyimpan status keluar akan menjadi sesuatu seperti
dan kemudian masing-masing memiliki skrip
Ini memberi Anda nama unik untuk setiap file status termasuk nama skrip yang membuatnya dan id prosesnya (jika lebih dari satu contoh skrip yang sama sedang berjalan) yang dapat Anda simpan untuk referensi nanti dan menempatkan semuanya di dalam tempat yang sama sehingga Anda bisa menghapus seluruh subdirektori setelah selesai.
Anda bahkan dapat menyimpan lebih dari satu status dari setiap skrip dengan melakukan sesuatu seperti
yang membuat file seperti sebelumnya, tetapi menambahkan string acak yang unik untuk itu.
Atau, Anda bisa menambahkan lebih banyak informasi status ke file yang sama.
sumber
script3
akan dieksekusi hanya jikascript1
danscript2
berhasil danscript1
danscript2
akan dieksekusi secara paralel:sumber