Bash: Banyak untuk loop di Background

8

Apakah ini cara yang benar untuk memulai beberapa proses berurutan di latar belakang?

for i in {1..10}; do
    for j in {1..10}; do
        run_command $i $j;
    done &
done;

Semua jharus diproses setelah satu sama lain untuk diberikan i, tetapi semua iharus diproses secara bersamaan.

Radio Terkendali
sumber
Apa yang Anda maksud dengan "cara yang benar"?
Eran Ben-Natan
Terutama itu berfungsi. Saya melewatkan ini di stackoverflow.
Radio Controlled
1
:-) Saya bertanya karena kode Anda berfungsi dengan baik untuk saya. Jika dengan "cara yang benar" yang Anda maksud praktik terbaik, maka saya akan meletakkan loop dalam fungsi atau bahkan file yang berbeda sehingga lebih jelas
Eran Ben-Natan

Jawaban:

8

Lingkaran luar yang Anda miliki pada dasarnya

for i in {1..10}; do
    some_compound_command &
done

Ini akan memulai sepuluh contoh bersamaan some_compound_commanddi latar belakang. Mereka akan dimulai secepat mungkin, tetapi tidak cukup "semuanya pada saat yang sama" (yaitu jika some_compound_commandmembutuhkan waktu sangat sedikit, maka yang pertama mungkin selesai sebelum yang terakhir dimulai).

Fakta yang some_compound_commandterjadi sebagai sebuah loop tidak penting. Ini berarti bahwa kode yang Anda tunjukkan adalah benar bahwa iterasi dari j-loop akan berjalan secara berurutan, tetapi semua instance dari loop dalam (satu per iterasi dari loop-luar i) akan dimulai secara bersamaan.

Satu-satunya hal yang perlu diingat adalah bahwa setiap pekerjaan latar belakang akan berjalan dalam subkulit. Ini berarti bahwa perubahan yang dibuat ke lingkungan (mis. Modifikasi nilai-nilai variabel shell, perubahan direktori kerja saat ini cd, dll.) Dalam satu contoh loop dalam tidak akan terlihat di luar pekerjaan latar belakang tertentu.

Apa yang mungkin ingin Anda tambahkan adalah waitpernyataan setelah loop Anda, hanya untuk menunggu semua pekerjaan latar belakang benar-benar selesai, setidaknya sebelum skrip berakhir:

for i in {1..10}; do
    for j in {1..10}; do
        run_command "$i" "$j"
    done &
done

wait
Kusalananda
sumber
3

Jika Anda memiliki GNU Paralel yang akan Anda lakukan:

parallel -j0 'for j in {1..10}; do run_command {} $j; done' ::: {1..10}

Salah satu manfaatnya adalah bahwa output dari menjalankan paralel run_commandstidak akan bercampur.

Ole Tange
sumber