Você não pode enviar uma atribuição para o segundo plano, já que o processo em segundo plano é uma bifurcação do shell, e as alterações na variável não são visíveis no shell principal.
Mas você pode executar várias tarefas em paralelo, fazer com que todas saiam para um canal e depois ler o que aparecer. Ou, na verdade, use substituição de processos , para evitar a emissão de comandos em um pipe sendo executados em uma subcamada (consulte < a href="https://unix.stackexchange.com/q/9954/170373"> Por que minha variável local está em um loop 'while read', mas não em outro loop aparentemente similar? )
Contanto que as saídas sejam linhas individuais escritas atomicamente, elas não serão mescladas, mas podem ser reordenadas:
$ task() { sleep 1; echo "$1"; }
$ time while read -r line; do arr+=("$line"); done < <(for x in 1 2 3 ; do task "$x" & done)
real 0m1.006s
$ declare -p arr
declare -a arr=([0]="2" [1]="1" [2]="3")
O acima irá executar todas as tarefas ao mesmo tempo. Há também o paralelo GNU (e -P
no GNU xargs), que é exatamente para executar tarefas em paralelo, e só vai correr alguns ao mesmo tempo. O Parallel também armazena em buffer as saídas das tarefas, para que você não obtenha dados misturados, mesmo que a tarefa grave linhas em partes.
$ mapfile -t arr < <(parallel -j4 bash ./task.sh ::: {a,b,c})
$ declare -p arr
declare -a arr=([0]="a" [1]="b" [2]="c")
(O mapfile
do Bash aqui lê as linhas de entrada para o array, similarmente ao loop while read .. arr+=()
acima).
A execução de um script externo como acima é simples, mas você pode realmente executar uma função exportada também, embora, é claro, todas as tarefas sejam executadas em cópias independentes do shell, para que tenham suas próprias cópias de cada variável, etc.
$ export -f task
$ mapfile -t arr < <(parallel task ::: {a,b,c})
O exemplo acima aconteceu para manter a
, b
e c
em ordem, mas isso é uma coincidência. Use parallel -k
para garantir que as saídas sejam mantidas em ordem.