0Pricing
Linux Command Line & Bash Scripting Mastery · Aula

Orquestração de cargas de trabalho com GNU parallel

Distribua grandes conjuntos de entrada entre os núcleos usando GNU parallel, espaços de tarefas e ordenação de resultados.

Orquestração de cargas de trabalho com GNU parallel é uma aula grátis de Linux Command Line & Bash Scripting Mastery no CoddyKit. Esta é a aula 3 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.

O que é o GNU parallel e por que usá-lo?

O GNU parallel é uma ferramenta de shell que permite executar tarefas em paralelo em uma ou várias máquinas. Em vez de processar uma lista grande de itens um por vez em um loop for, o parallel distribui esse trabalho simultaneamente entre todos os núcleos disponíveis da CPU.

  • Velocidade: uma tarefa que leva 8 minutos sequencialmente pode terminar em cerca de 1 minuto em uma máquina com 8 núcleos.
  • Simplicidade: aceita entradas da entrada padrão, de arquivos ou de listas de argumentos — sem gerenciamento manual de processos.
  • Segurança: a saída de tarefas diferentes é mantida separada; os resultados nunca ficam intercalados.

Instale-o com sudo apt install parallel (Debian/Ubuntu) ou brew install parallel (macOS). Verifique a instalação com parallel --version.

Seu primeiro comando parallel

A forma mais simples de usar parallel lê itens da entrada padrão e executa um comando para cada um deles. O marcador {} representa o item de entrada atual.

O exemplo abaixo compacta simultaneamente cinco arquivos de registro usando gzip. Sem o parallel, cada arquivo seria compactado um após o outro. Com ele, até N arquivos (onde N = número de núcleos da CPU) são compactados ao mesmo tempo.

#!/usr/bin/env bash
# Create sample files first
for i in 1 2 3 4 5; do
  dd if=/dev/urandom bs=1M count=2 of="log_${i}.txt" 2>/dev/null
done

# Compress all of them in parallel
ls log_*.txt | parallel gzip {}

echo "Done. Compressed files:"
ls log_*.txt.gz

Controlando posições de tarefas com -j

Por padrão, o parallel executa uma tarefa por núcleo da CPU. Você pode substituir esse comportamento com o sinalizador -j (ou --jobs).

  • -j 4 — executa exatamente 4 tarefas simultaneamente
  • -j 0 — executa tantas tarefas quanto o número de entradas (use com cuidado!)
  • -j 200% — executa o dobro de tarefas em relação ao número de núcleos da CPU (útil para trabalhos limitados por E/S)
  • -j 50% — usa apenas metade dos núcleos disponíveis

Para tarefas limitadas pela CPU, -j $(nproc) costuma ser ideal. Para tarefas de E/S de rede ou de disco, você pode ultrapassar com segurança a quantidade de núcleos, pois as tarefas passam a maior parte do tempo aguardando.

#!/usr/bin/env bash
# Show how many cores are available
echo "CPU cores: $(nproc)"

# Run 8 sleep jobs but limit to 3 at a time
# -j 3 means at most 3 jobs run simultaneously
seq 1 8 | parallel -j 3 'echo "Starting job {}"; sleep 1; echo "Done job {}"'

echo "All jobs finished."

Lendo entradas de arquivos e argumentos

O parallel é flexível quanto à origem da lista de entradas. Você não está limitado a usar um pipe a partir da entrada padrão.

  • De um arquivo: parallel -a urls.txt wget {}
  • Lista de argumentos inserida diretamente: parallel echo ::: apple banana cherry
  • Várias fontes de argumentos (produto cartesiano): parallel echo {1}-{2} ::: a b c ::: 1 2 — produz a-1, a-2, b-1, b-2, c-1, c-2
  • Explicitamente da entrada padrão: cat list.txt | parallel -j4 process {}

O separador ::: informa ao parallel que os valores seguintes devem ser usados como fonte de argumentos, em vez de serem lidos da entrada padrão.

#!/usr/bin/env bash
# Inline list with :::
parallel echo 'Hello from {}' ::: Alice Bob Carol Dave

echo '---'

# Cartesian product: combine two lists
# Generates: dev-v1, dev-v2, prod-v1, prod-v2
parallel echo 'Deploy {1} to env {2}' ::: v1 v2 ::: dev prod

Marcadores: manipulando tokens de entrada

O parallel oferece várias substituições de marcadores que permitem extrair automaticamente partes da string de entrada — algo muito útil quando as entradas são caminhos de arquivos.

  • {} — o item de entrada completo
  • {.} — a entrada sem sua extensão de arquivo (report.csv → report)
  • {/} — apenas o nome base (remove o caminho do diretório)
  • {//} — apenas o caminho do diretório
  • {/.} — nome base sem extensão

Isso elimina a necessidade de chamadas a basename / dirname dentro do comando da tarefa, tornando as canalizações mais limpas e rápidas.

#!/usr/bin/env bash
# Demonstrate placeholder substitutions
parallel --dry-run 'convert {} -resize 800x600 {.}_thumb.jpg' \
  ::: /photos/vacation/beach.png /photos/work/team.png

# {.}  strips extension: /photos/vacation/beach
# Result command shown (--dry-run does NOT execute):
#  convert /photos/vacation/beach.png -resize 800x600 /photos/vacation/beach_thumb.jpg
#  convert /photos/work/team.png      -resize 800x600 /photos/work/team_thumb.jpg
echo 'No files were changed (dry run)'

Mantendo a saída ordenada com --keep-order

Quando as tarefas terminam em momentos diferentes, a saída da saída padrão aparece na ordem em que elas são concluídas. Isso pode dificultar a leitura dos registros e tornar a análise posterior não confiável.

Dois sinalizadores controlam a ordenação da saída:

  • --keep-order (-k) — exibe a saída de cada tarefa na mesma ordem das entradas, mesmo que uma tarefa posterior termine primeiro. A saída fica armazenada em buffer até que as tarefas anteriores sejam concluídas.
  • --line-buffer — uma solução intermediária: exibe linhas completas assim que chegam, sem esperar a conclusão da tarefa, mas nunca intercala linhas parcialmente escritas.

Use -k quando o consumidor posterior espera resultados na ordem das entradas (por exemplo, ao criar um relatório ordenado). Omita-o quando a ordem não importar e você quiser ver os resultados o mais rápido possível.

#!/usr/bin/env bash
# Without -k: output order is unpredictable
echo '--- Without --keep-order ---'
seq 5 1 1 | parallel 'sleep 0.$((RANDOM % 5)); echo "Result for {}"'

echo

# With -k: output always appears as 5, 4, 3, 2, 1
echo '--- With --keep-order (-k) ---'
seq 5 1 1 | parallel -k 'sleep 0.$((RANDOM % 5)); echo "Result for {}"'

Agrupamento da saída para evitar intercalações

Mesmo com a saída ordenada, se um trabalho imprimir várias linhas, essas linhas poderão ser intercaladas com linhas de outro trabalho em execução ao mesmo tempo. parallel resolve isso automaticamente armazenando em buffer toda a saída padrão e a saída de erro de cada trabalho e, em seguida, imprimindo-as como um único bloco atômico quando o trabalho termina.

Esse comportamento vem ativado por padrão. Pode desativá-lo com --ungroup se precisar transmitir a saída em tempo real (por exemplo, em trabalhos de longa duração com barras de progresso), mas, nesse caso, as intercalações poderão ocorrer novamente.

  • Padrão: a saída é agrupada por trabalho — seguro para análise.
  • --ungroup: a saída é transmitida em tempo real — ideal para monitoramento interativo.
  • --line-buffer: uma solução intermediária — as linhas nunca são divididas, mas os trabalhos podem ser intercalados nos limites entre linhas.

Passando argumentos dentro de funções do shell

Às vezes, o trabalho que deseja executar em paralelo é mais do que um único comando — é uma função do shell com várias etapas. Pode passar uma função para parallel usando export -f combinado com env_parallel ou chamando bash -c diretamente.

A abordagem portátil mais segura para trabalhos complexos é o padrão bash -c '...'. O marcador {} é passado como $1 quando termina com _ {}.

#!/usr/bin/env bash
# Define a multi-step processing function
process_item() {
  local item="$1"
  echo "[START] $item"
  # Simulate two steps
  sleep 0.2
  local result=$(echo "$item" | tr '[:lower:]' '[:upper:]')
  echo "[END]   $item -> $result"
}

export -f process_item

# Run the function in parallel for each input
echo 'alpha beta gamma delta epsilon' | tr ' ' '\n' \
  | parallel -j 3 process_item {}

Limitação de taxa e novas tentativas com --delay e --retries

Ao acessar serviços externos (APIs, servidores remotos e bancos de dados) em paralelo, geralmente é necessário limitar a taxa e garantir tolerância a falhas.

  • --delay N — aguarda N segundos entre o início de cada novo trabalho (valores fracionários, como 0.5, são permitidos). Evita sobrecarregar um serviço.
  • --retries N — se um trabalho terminar com um status diferente de zero, tenta executá-lo novamente até N vezes antes de desistir. Cada nova tentativa conta como um novo espaço de trabalho.
  • --timeout N — encerra um trabalho se ele durar mais de N segundos. Combinado com --retries, isso trata trabalhos travados de forma adequada.

Exemplo: baixar 50 URLs com no máximo 4 conexões simultâneas, um atraso de inicialização de 0,5 s entre os inícios e 3 novas tentativas em caso de falha.

#!/usr/bin/env bash
# Simulate downloading URLs with throttling and retries
# (using echo instead of curl so this is self-contained)

download_url() {
  local url="$1"
  # Randomly fail ~30% of the time to demo --retries
  if (( RANDOM % 10 < 3 )); then
    echo "FAIL: $url" >&2
    return 1
  fi
  echo "OK:   $url downloaded"
}

export -f download_url

printf 'https://example.com/file%d\n' $(seq 1 10) \
  | parallel -j 4 --delay 0.2 --retries 3 download_url {}

echo 'All downloads attempted.'

Distribuindo trabalho entre hosts remotos com --sshloginfile

parallel pode distribuir trabalhos de forma transparente para máquinas remotas por SSH, funcionando como uma ferramenta leve de computação em cluster sem exigir nenhum software especial de cluster.

  • --sshlogin user@host — executa trabalhos em um host remoto específico.
  • --sshloginfile machines.txt — lê uma lista de hosts de um arquivo, um por linha. Use : como uma entrada especial para também usar a máquina local.
  • --transfer — copia o arquivo de entrada para o host remoto antes do processamento.
  • --return {} — copia o arquivo de resultado de volta depois que o trabalho termina.
  • --cleanup — exclui do host remoto os arquivos transferidos após a recuperação.

O host remoto precisa ter parallel instalado e a autenticação baseada em chaves SSH configurada, sem solicitações de senha.

Relatórios de progresso e registro

Para cargas de trabalho de longa duração, é essencial monitorar o progresso e diagnosticar falhas posteriormente.

  • --progress — imprime uma linha de resumo em tempo real mostrando quantos trabalhos estão em execução, foram concluídos e ainda faltam.
  • --eta — estima o tempo até a conclusão com base na duração média dos trabalhos até o momento.
  • --joblog results.log — grava um arquivo de registro separado por tabulações, com uma linha para cada trabalho concluído, incluindo o código de saída, o tempo de execução e o comando executado. É extremamente útil para auditar falhas.
  • --resume --joblog results.log — ignora os trabalhos que já aparecem, com código de saída 0, no arquivo de registro. Se uma execução em lote for interrompida, poderá retomá-la sem refazer o trabalho concluído com sucesso.

A combinação de --joblog + --resume é um dos recursos mais poderosos do GNU parallel para criar fluxos de processamento robustos em produção.

#!/usr/bin/env bash
LOGFILE="/tmp/parallel_demo_$$.log"

# Run jobs and record results to a log
seq 1 12 | parallel \
  --jobs 4 \
  --progress \
  --joblog "$LOGFILE" \
  'sleep 0.1; echo "Processed item {}"'

echo
echo '=== Job Log (first 5 entries) ==='
head -6 "$LOGFILE"

# Show only failed jobs (exit value != 0)
echo '=== Failed jobs ==='
awk 'NR>1 && $7 != 0 { print $0 }' "$LOGFILE" || echo '(none)'

rm -f "$LOGFILE"

Verificação de conhecimento: opções de espaços de trabalho

Teste sua compreensão de como parallel controla a simultaneidade.

Recapitulação da lição: orquestrando cargas de trabalho com GNU parallel

Você estudou o conjunto de ferramentas essenciais para distribuir grandes conjuntos de entrada entre núcleos da CPU com o GNU parallel. Veja os pontos principais:

  • Uso básico: encaminhe uma lista para parallel command {} — {} é substituído por cada item de entrada.
  • Espaços de trabalho (-j): controlam a simultaneidade com precisão — use a quantidade de núcleos para trabalhos limitados pela CPU e percentuais maiores para trabalhos limitados por entrada e saída.
  • Marcadores ({.}, {/}, {//}, {/.}) extraem componentes de caminhos de forma simples, sem comandos adicionais.
  • Controle da saída: -k preserva a ordem da entrada; o agrupamento padrão evita linhas intercaladas; --ungroup permite a transmissão em tempo real.
  • Resiliência: --retries, --timeout e --delay tornam os fluxos de processamento paralelos robustos contra trabalhos instáveis e limites de taxa.
  • Auditabilidade: --joblog registra o resultado de cada trabalho; --resume permite retomar a execução do ponto em que foi interrompida.
  • Escalonamento horizontal: --sshloginfile distribui trabalhos para máquinas remotas por SSH, sem sobrecarga de cluster.

Dominar essas opções transforma parallel em um orquestrador de cargas de trabalho pronto para produção, integrado diretamente ao seu shell.

Perguntas Frequentes

A aula “Orquestração de cargas de trabalho com GNU parallel” é grátis?

Sim — o texto completo de “Orquestração de cargas de trabalho com GNU parallel” é 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 “Orquestração de cargas de trabalho com GNU parallel”?

Distribua grandes conjuntos de entrada entre os núcleos usando GNU parallel, espaços de tarefas e ordenação de resultados. 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 3 de 4.

Quanto tempo leva a aula “Orquestração de cargas de trabalho com GNU parallel”?

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

  1. Criação de perfis de desempenho e prevenção de subshells inúteis
  2. Paralelismo com xargs -P e tarefas em segundo plano
  3. Orquestração de cargas de trabalho com GNU parallel
  4. Pipelines de transmissão e pipes nomeados para maior vazão
← Voltar para Linux Command Line & Bash Scripting Mastery