Linux: Pipes e Filtros — A Essência da Filosofia Unix
O núcleo da filosofia Unix é "faça uma coisa bem feita". O pipe | encadeia esses pequenos programas — a saída de um se torna a entrada do próximo.
📋 Pré-requisitos: Você deve primeiro concluir
- Aula 12: Streams Padrão e Redirecionamento
1. O Que Você Vai Aprender
- Como os pipes
|funcionam - sort para ordenar e uniq para deduplicar
- wc para contar linhas/palavras/caracteres
- tee para saída dupla
- A arte de combinar pipelines de múltiplos estágios
2. A História de um Arquivo de Log de 10GB
(1) O Problema: Logs Grandes Demais Para Navegar Manualmente
Alex precisava encontrar os 10 IPs mais frequentes em um log de acesso do Nginx de 10GB. Abrir em um editor era impossível (10GB não abre) e escrever um script Python era exagero.
(2) O Poder de um Pipeline de Uma Linha
Bob ensinou-lhe a combinar comandos com pipes:
cat access.log | awk '{print $1}' | sort | uniq -c | sort -rn | head -10
ℹ️ Nota:
cat file | commandé comum, mas ocataqui apenas passa o conteúdo do arquivo para o pipe — usarcommand < fileouawk '{...}' filediretamente é mais eficiente, economizando um processo. Isso é chamado "UUOC" (Useless Use of Cat); embora funcione bem, pode ser otimizado para desempenho.
Saída:
45231 192.168.1.100
38902 10.0.0.45
21045 192.168.1.200
(3) O Benefício: Tarefas Complexas em Um Comando
Alex descobriu que combinações de pipelines podem lidar com praticamente qualquer tarefa de extração de dados — contagem, filtragem, ordenação, ranking, deduplicação. Um único comando é um mini pipeline de processamento de dados.
3. Pontos-Chave
(1) Como os Pipes Funcionam
comando1 | comando2 | comando3
│ │ │
│ saída │ saída │
└──────────→│──────────→│──────────→ Saída final
│ │
stdout do comando1 conecta ao stdin do comando2
(2) Filtros Comuns
| Comando | Finalidade | Opções comuns |
|---|---|---|
sort |
Ordenar | -n numérico, -r reverso, -k por coluna, -u ordena e deduplica |
uniq |
Deduplicar (adjacentes) | -c contar, -d mostrar só duplicados, -u mostrar só únicos |
wc |
Contar | -l linhas, -w palavras, -c caracteres |
head |
Mostrar início | -n 10 primeiras 10 linhas, -c 100 primeiros 100 caracteres |
tail |
Mostrar fim | -n 10 últimas 10 linhas, -f seguir em tempo real |
tee |
Dividir stream | Saída para arquivo e tela ao mesmo tempo |
tee recebeu esse nome por causa da "junção em T" da hidráulica — ele divide os dados do pipeline em dois, passando uma cópia adiante e gravando outra em um arquivo. Ao depurar um pipeline, insira tee /tmp/debug.txt no meio para capturar resultados intermediários sem afetar a saída final.
| nl | Numerar linhas | -ba numerar todas as linhas |
(3) ▶ Exemplo: Contar Informações de Arquivos
# Contar o número de arquivos
ls -la | wc -l
# Nota: wc -l inclui a linha "total", então o número real de arquivos é um a menos
# Contar o total de linhas em todos os arquivos .md
cat *.md | wc -l
# Mostrar o uso de disco do diretório atual
ls -lh | tail -n +2 | awk '{print $5, $9}'
Saída:
TEXT15 342 4.0K config.yml 12M data.tar.gz
(4) ▶ Exemplo: Ordenação e Deduplicação
# Ordenar endereços IP (alfabético vs numérico)
cat << EOF | sort
192.168.1.100
10.0.0.45
192.168.1.200
10.0.0.2
EOF
# sort -n para ordenação numérica (por segmento do IP)
cat << EOF | sort -t. -k1,1n -k2,2n -k3,3n -k4,4n
192.168.1.100
10.0.0.45
192.168.1.200
10.0.0.2
EOF
# Deduplicar e contar
cat << EOF | sort | uniq -c | sort -rn
apple
banana
apple
orange
banana
apple
EOF
Saída:
TEXT10.0.0.2 10.0.0.45 192.168.1.100 192.168.1.200 3 apple 2 banana 1 orange
(5) ▶ Exemplo: head e tail
# Ver as 5 primeiras linhas
ls -la /etc | head -5
# Ver as 5 últimas linhas
ls -la /etc | tail -5
# Mostrar linhas 10-20
cat arquivo-longo.txt | head -20 | tail -11
# Acompanhar um log em tempo real (pressione Ctrl+C para sair)
tail -f /var/log/syslog
# Ver as últimas 10 entradas de log
tail -f -n 10 /var/log/syslog
Saída:
TEXTtotal 72 drwxr-xr-x 2 root root 4096 Jul 7 10:00 bin drwxr-xr-x 3 root root 4096 Jul 7 10:00 lib drwxrwxrwt 15 root root 4096 Jul 7 10:30 tmp
# Ver resultados na tela e salvar em arquivo ao mesmo tempo
ls -la | tee saida.txt
# Modo anexar
echo "Novo conteúdo" | tee -a saida.txt
# Salvar resultados intermediários do pipeline
ps aux | tee processos.txt | grep nginx
# Primeiro salva todos os processos com tee, depois filtra por nginx
Saída:
TEXTtotal 72 drwxr-xr-x 2 root root 4096 Jul 7 10:00 bin ... Novo conteúdo root 1234 0.0 0.1 nginx: master
(6) ▶ Exemplo: Combinações Práticas de Pipeline
# 5 maiores arquivos
ls -lhS | head -6
# Número de Shells em execução
ps aux | grep bash | wc -l
# Partições com uso de disco acima de 80%
df -h | grep -v "tmpfs" | awk '{print $5, $6}' | sort -rn
# Encontrar arquivos de log em /var/log modificados nos últimos 7 dias
find /var/log -name "*.log" -mtime -7 | sort
# Obter o IP externo
curl -s ifconfig.me | tee meu-ip.txt
Saída:
TEXT-r--r--r-- 1 root root 12K config.pkt -rw-r--r-- 1 root root 8.9M data.tar.gz 3 203.0.113.42
(7) ▶ Exemplo Abrangente: Cadeia de Pipeline de Análise de Log
# Simular um log de acesso do Nginx
cat << 'EOF' > /tmp/access.log
192.168.1.100 - - [07/Jul/2026:10:15:30 +0000] "GET /index.html HTTP/1.1" 200 1234
10.0.0.45 - - [07/Jul/2026:10:16:30 +0000] "GET /api/users HTTP/1.1" 200 5678
192.168.1.100 - - [07/Jul/2026:10:17:30 +0000] "POST /api/login HTTP/1.1" 401 234
10.0.0.45 - - [07/Jul/2026:10:18:30 +0000] "GET /api/users HTTP/1.1" 200 5678
192.168.1.200 - - [07/Jul/2026:10:19:30 +0000] "GET /index.html HTTP/1.1" 404 123
10.0.0.45 - - [07/Jul/2026:10:20:30 +0000] "GET /api/users HTTP/1.1" 200 5678
EOF
echo "=== Total de Requisições ==="
wc -l /tmp/access.log
echo ""
echo "=== Contagem de Acesso por IP (Top 5) ==="
cat /tmp/access.log | awk '{print $1}' | sort | uniq -c | sort -rn
echo ""
echo "=== Contagem por Código de Status HTTP ==="
cat /tmp/access.log | awk '{print $9}' | sort | uniq -c | sort -rn
echo ""
echo "=== URLs Mais Acessadas ==="
cat /tmp/access.log | awk '{print $7}' | sort | uniq -c | sort -rn | head -5
echo ""
echo "=== Requisições com Erro 404 ==="
grep " 404 " /tmp/access.log | awk '{print $1, $7}'
❓ Perguntas Frequentes
P: Pipelines são processados em série ou em paralelo? R: \1
P: Pipes e redirecionamento podem ser usados juntos? R: Sim. Por exemplo,
command > file 2>&1(redirecionamento) ecommand | grep "erro"(pipe) podem ser combinados:command 2>&1 | grep "erro".
P: Um erro no meio do pipeline afeta o resultado final? R: Sim. Se um comando no pipeline falhar, os comandos downstream podem receber dados incompletos. Use
set -o pipefail(em scripts) para que a falha de qualquer comando do pipeline cause a falha do pipeline inteiro.
P: Como saio do
tail -f? R: PressioneCtrl + C. Otail -fmonitora continuamente o arquivo em busca de novo conteúdo até que você o interrompa manualmente.
P: O processamento de pipelines com arquivos grandes esgota a memória? R: \1
📖 Resumo
- Pipe
|conecta comandos: stdout do comando anterior → stdin do próximo sortordena,uniq -cdeduplica e conta,wc -lconta linhashead -nmostra as primeiras N linhas,tail -fsegue em tempo real,teedivide a saída- Exemplo de combinação:
cat log | awk '{print $1}' | sort | uniq -c | sort -rn | head -10 - Pipelines são paralelos e em streaming — processar arquivos grandes não esgota a memória
📝 Exercícios
- Básico (Dificuldade ⭐): Use
ls -la | wc -lpara contar arquivos, depois use/var/log/syslogou crie um arquivo de teste para extrair linhas que contêm "erro" e contá-las - Intermediário (Dificuldade ⭐⭐): Use
df -h | grep "^/" | sort -k5 -rnpara encontrar a partição com o maior uso de disco, e useteepara salvar a saída deps auxem um arquivo enquanto exibe no terminal - Avançado (Dificuldade ⭐⭐⭐): Combine 3 ou mais comandos de pipeline para uma tarefa de processamento de dados — encontre os 5 processos que mais consomem memória no sistema, ordenados por uso de memória em ordem decrescente, formatados como "PID Comando Memória%"