Paralelismo com xargs -P e tarefas em segundo plano
Execute tarefas independentes simultaneamente usando o modo paralelo do xargs e grupos gerenciados de tarefas em segundo plano.
Paralelismo com xargs -P e tarefas em segundo plano é uma aula grátis de Linux Command Line & Bash Scripting Mastery no CoddyKit. Esta é a aula 2 de 4. Você pode ler a aula completa abaixo gratuitamente — depois pratica ao vivo no navegador com um editor de código integrado e um tutor de IA 24/7. Faz parte do caminho de aprendizado de Linux Command Line & Bash Scripting Mastery, e seu progresso é sincronizado entre a web e o app CoddyKit. O curso de Linux Command Line & Bash Scripting Mastery inclui 4 aulas no total.
Por que a execução sequencial é lenta
Quando você executa comandos um após o outro em um script de shell, deixa os núcleos da CPU ociosos. Considere redimensionar 500 imagens: cada chamada a convert usa um núcleo, enquanto os outros sete ficam ociosos.
O paralelismo resolve isso distribuindo várias tarefas simultaneamente. Duas ferramentas principais do Bash facilitam esse trabalho:
- xargs -P — distribui uma lista de entradas entre N processos de trabalho paralelos
- tarefas em segundo plano (&) + wait — cria processos manualmente e aguarda sua conclusão
Esta lição aborda as duas opções para que você possa escolher a ferramenta adequada a cada situação.
Revisão dos conceitos básicos de xargs
Antes de adicionar paralelismo, relembre como xargs funciona. Ele lê itens da entrada padrão e os passa como argumentos para um comando.
O sinalizador -I {} permite colocar o item de entrada em qualquer posição da string de comando, não apenas no final.
O exemplo abaixo converte cada arquivo .txt para maiúsculas usando tr. Cada arquivo é processado individualmente (referência sequencial).
#!/usr/bin/env bash
# Create sample files
mkdir -p /tmp/xargs_demo
for i in 1 2 3; do
echo "hello world $i" > /tmp/xargs_demo/file$i.txt
done
# Process files one at a time (sequential)
find /tmp/xargs_demo -name '*.txt' | xargs -I {} sh -c 'tr a-z A-Z < "$1"' _ {}
# Cleanup
rm -rf /tmp/xargs_demoIntrodução ao xargs -P
Adicione o sinalizador -P N ao xargs para executar até N processos em paralelo. O xargs gerencia automaticamente o conjunto de processos de trabalho — quando uma posição fica livre, o próximo item começa imediatamente.
-P 0— cria tantos processos quanto o número de entradas (use com cuidado em listas grandes)-P 4— mantém no máximo 4 processos de trabalho em execução a qualquer momento-n 1— envia exatamente um item de entrada por processo invocado (sinalizador complementar comum)
Juntos, -n 1 -P 4 formam o padrão mais comum: um item por processo de trabalho, com quatro processos simultâneos.
#!/usr/bin/env bash
# Simulate 8 tasks, each taking ~1 second
# Sequential would take ~8s; parallel with -P 4 takes ~2s
process_item() {
local item="$1"
sleep 1
echo "Done: $item"
}
export -f process_item
time printf '%s\n' task{1..8} | xargs -n 1 -P 4 bash -c 'process_item "$@"' _Processamento paralelo de arquivos
Um caso de uso prático é compactar muitos arquivos de registro simultaneamente. Sem -P, cada chamada a gzip bloqueia a próxima. Com -P 8, até oito compactações são executadas ao mesmo tempo, utilizando todos os núcleos da CPU.
Observe como -n 1 garante que cada processo de trabalho paralelo receba exatamente um nome de arquivo — algo essencial quando os nomes podem conter espaços (combine com -d '\n' ou -print0 / -0 para maior segurança).
#!/usr/bin/env bash
# Create dummy log files
mkdir -p /tmp/logs_demo
for i in $(seq 1 12); do
dd if=/dev/urandom bs=1K count=64 2>/dev/null > /tmp/logs_demo/app_$i.log
done
echo "Files before: $(ls /tmp/logs_demo | wc -l)"
# Compress all .log files in parallel (up to 8 workers)
find /tmp/logs_demo -name '*.log' -print0 \
| xargs -0 -n 1 -P 8 gzip --fast
echo "Files after : $(ls /tmp/logs_demo | wc -l)"
rm -rf /tmp/logs_demoEscolhendo o valor adequado para -P
Definir -P com um valor muito baixo desperdiça núcleos; com um valor muito alto, causa excesso de alternância entre processos. Um bom ponto de partida é o número de núcleos lógicos da CPU:
- Tarefas limitadas pela CPU (compactação, codificação):
-P $(nproc) - Tarefas limitadas por E/S (chamadas de rede, leituras de disco):
-P $(($(nproc) * 4))ou mais, pois os processos de trabalho passam a maior parte do tempo aguardando - Tarefas limitadas pela memória: calcule
available_RAM / task_RAM_usagee limite o valor nesse ponto
nproc retorna o número de unidades de processamento disponíveis, funcionando como uma alternativa portátil a números definidos manualmente.
#!/usr/bin/env bash
CORES=$(nproc)
IO_WORKERS=$(( CORES * 4 ))
echo "CPU cores : $CORES"
echo "CPU-bound -P: $CORES"
echo "I/O-bound -P: $IO_WORKERS"
# Example: parallel curl downloads (I/O-bound)
# printf '%s\n' url1 url2 ... | xargs -n 1 -P "$IO_WORKERS" curl -sSOTarefas em segundo plano com &
Às vezes, você precisa de mais controle do que o xargs oferece — tratamento de erros por tarefa, listas dinâmicas ou formatos de argumentos complexos. Use o operador de segundo plano integrado ao shell & para criar tarefas manualmente.
Adicionar & a qualquer comando devolve imediatamente o controle ao script. O processo filho é executado em segundo plano enquanto o processo pai continua. Chame wait no final para bloquear a execução até que todos os processos filhos terminem.
#!/usr/bin/env bash
process() {
local id="$1"
sleep $(( RANDOM % 3 + 1 ))
echo "Job $id finished at $(date +%T)"
}
echo "Launching 5 background jobs..."
for id in $(seq 1 5); do
process "$id" &
done
wait # Block until every background job completes
echo "All jobs done."Limitando a concorrência com um conjunto de tarefas
Criar todas as tarefas de uma só vez com & pode esgotar a memória quando a lista é grande. Um conjunto de tarefas mantém no máximo N tarefas em execução a qualquer momento:
- Depois de criar cada tarefa, verifique quantas tarefas em segundo plano estão ativas usando
jobs -r | wc -l - Se a contagem atingir o limite, chame
wait -n(Bash 4.3+) para aguardar a conclusão de qualquer uma das tarefas antes de criar a próxima
Esse padrão imita o funcionamento interno de xargs -P, mas oferece flexibilidade total para criar scripts em torno de cada tarefa.
#!/usr/bin/env bash
MAX_JOBS=3
process() {
local id="$1"
sleep $(( RANDOM % 3 + 1 ))
echo "Task $id done"
}
for id in $(seq 1 10); do
# Throttle: wait for a slot if pool is full
while (( $(jobs -r | wc -l) >= MAX_JOBS )); do
wait -n 2>/dev/null || true
done
process "$id" &
done
wait
echo "All 10 tasks complete."Capturando códigos de saída de tarefas paralelas
Uma preocupação importante com tarefas em segundo plano é que, se um processo filho falhar, o script pai não fica sabendo automaticamente. Você precisa capturar o PID de cada filho e verificar seu status de saída com wait <pid>.
O padrão abaixo armazena cada PID em uma matriz e, em seguida, percorre a matriz chamando wait "$pid", que retorna o código de saída desse filho específico.
#!/usr/bin/env bash
set -euo pipefail
task() {
local id="$1"
sleep 1
if (( id == 3 )); then
echo "Task $id: FAILED" >&2
return 1
fi
echo "Task $id: ok"
}
pids=()
for id in $(seq 1 5); do
task "$id" &
pids+=("$!")
done
failed=0
for pid in "${pids[@]}"; do
if ! wait "$pid"; then
echo "PID $pid exited with error" >&2
(( failed++ ))
fi
done
(( failed == 0 )) && echo "All OK" || { echo "$failed job(s) failed"; exit 1; }Downloads paralelos com xargs -P
A E/S de rede é um caso clássico para alto paralelismo — cada processo de trabalho passa a maior parte do tempo aguardando bytes. O exemplo abaixo busca várias URLs simultaneamente e salva cada uma em um arquivo com nome exclusivo.
Principais sinalizadores usados:
-P 8— oito processos curl simultâneos-n 1— uma URL por invocação do curl--create-dirs -o— o curl salva em um nome de arquivo derivado
#!/usr/bin/env bash
# Download several small public files in parallel
URLs=(
"https://httpbin.org/bytes/1024"
"https://httpbin.org/bytes/2048"
"https://httpbin.org/bytes/512"
"https://httpbin.org/bytes/4096"
)
mkdir -p /tmp/parallel_dl
printf '%s\n' "${URLs[@]}" | xargs -n 1 -P 4 bash -c '
url="$1"
out="/tmp/parallel_dl/$(echo "$url" | md5sum | cut -c1-8).bin"
curl -sSf "$url" -o "$out" && echo "Saved $out"
' _
ls -lh /tmp/parallel_dl/
rm -rf /tmp/parallel_dlCombinando find, xargs -P e funções do shell
Para usar uma função do shell com várias linhas com xargs, você precisa exportá-la com export -f function_name e, em seguida, invocá-la por meio de bash -c 'function_name "$@"' _ dentro do xargs.
Esse padrão permite aproveitar todo o poder dos scripts em cada processo de trabalho paralelo: registro de eventos, tratamento de erros e lógica condicional — tudo por item.
#!/usr/bin/env bash
mkdir -p /tmp/proc_demo
for i in $(seq 1 8); do echo "data $i" > /tmp/proc_demo/item_$i.txt; done
process_file() {
local f="$1"
local base
base=$(basename "$f" .txt)
# Simulate work: count words and append a timestamp
local wc
wc=$(wc -w < "$f")
echo "[$base] words=$wc processed=$(date +%T)" >> "/tmp/proc_demo/${base}.result"
}
export -f process_file
find /tmp/proc_demo -name '*.txt' -print0 \
| xargs -0 -n 1 -P "$(nproc)" bash -c 'process_file "$@"' _
grep '' /tmp/proc_demo/*.result
rm -rf /tmp/proc_demoMedindo o ganho de velocidade com time
Sempre faça medições antes de afirmar que houve melhoria. Envolva o comando paralelo com time e compare-o com a referência sequencial. O ganho real de velocidade depende de:
- Independência das tarefas — as tarefas não devem compartilhar estado gravável sem bloqueios
- Custo adicional — o custo de criar um processo (cerca de 5 a 20 ms cada) é relevante para tarefas pequenas
- Disputa por recursos — a E/S de disco pode atingir seu limite antes mesmo da CPU
Um padrão simples de referência é mostrado abaixo: execute primeiro de forma sequencial, depois em paralelo, e compare os tempos de relógio de parede real.
#!/usr/bin/env bash
work() { sleep 0.2; } # simulate a 200ms task
export -f work
ITEMS=$(seq 1 16)
echo "=== Sequential ==="
time printf '%s\n' $ITEMS | xargs -n 1 bash -c 'work' _
echo
echo "=== Parallel ($(nproc) workers) ==="
time printf '%s\n' $ITEMS | xargs -n 1 -P "$(nproc)" bash -c 'work' _Verificação de conhecimentos: comportamento de xargs -P
Teste sua compreensão sobre a execução paralela com xargs -P.
Recapitulação da lição
Agora você dispõe de duas técnicas confiáveis para execução paralela no Bash:
- xargs -n 1 -P N — a abordagem mais simples; o xargs gerencia automaticamente o conjunto de processos de trabalho. É melhor quando sua entrada é uma lista simples e cada item corresponde a um comando.
- tarefas em segundo plano (&) + wait — oferece controle total sobre o script; é essencial quando você precisa dos PIDs de cada tarefa, de entradas dinâmicas ou de um tratamento detalhado dos códigos de saída. Use
wait -ncom um contador para limitar a concorrência.
Regras importantes para as próximas etapas:
- Exporte as funções do shell com
export -fantes de passá-las peloxargs - Use
-print0/-0para tratar com segurança nomes de arquivos que contenham espaços - Capture os PIDs em uma matriz e chame
wait "$pid"individualmente para detectar falhas - Faça referências de desempenho com
time— o paralelismo só é vantajoso quando o custo adicional da tarefa supera o custo de criar o processo - Defina
-P $(nproc)para tarefas limitadas pela CPU e um múltiplo maior para cargas de trabalho limitadas por E/S
Perguntas Frequentes
A aula “Paralelismo com xargs -P e tarefas em segundo plano” é grátis?
Sim — o texto completo de “Paralelismo com xargs -P e tarefas em segundo plano” é grátis para ler aqui na web. Para praticá-la interativamente (um editor de código integrado e um tutor de IA 24/7) e desbloquear o restante do curso de Linux Command Line & Bash Scripting Mastery, atualize para CoddyKit PRO. O curso de Linux Command Line & Bash Scripting Mastery inclui 4 aulas no total.
O que vou aprender em “Paralelismo com xargs -P e tarefas em segundo plano”?
Execute tarefas independentes simultaneamente usando o modo paralelo do xargs e grupos gerenciados de tarefas em segundo plano. Você pratica Linux Command Line & Bash Scripting Mastery com código prático que executa diretamente no navegador, e um tutor de IA 24/7 responde suas dúvidas enquanto trabalha na aula.
Preciso ter experiência prévia para começar Linux Command Line & Bash Scripting Mastery?
Nenhuma experiência prévia é necessária. Linux Command Line & Bash Scripting Mastery no CoddyKit é estruturado para alunos iniciantes até avançados, então você pode começar aqui ou desde o início e aprender no seu ritmo. Esta é a aula 2 de 4.
Quanto tempo leva a aula “Paralelismo com xargs -P e tarefas em segundo plano”?
A maioria das aulas CoddyKit leva cerca de 5–10 minutos. Cada uma é compacta e interativa, então você faz progresso constante e retoma exatamente de onde parou entre web e app.
Posso escrever e executar código nesta aula de Linux Command Line & Bash Scripting Mastery?
Sim. Cada aula de Linux Command Line & Bash Scripting Mastery inclui um editor de código integrado, então você escreve e executa código real direto no navegador e recebe feedback de IA instantaneamente — nenhuma configuração local necessária.
Todas as aulas deste curso
- Criação de perfis de desempenho e prevenção de subshells inúteis
- Paralelismo com xargs -P e tarefas em segundo plano
- Orquestração de cargas de trabalho com GNU parallel
- Pipelines de transmissão e pipes nomeados para maior vazão