Shell scripting é uma habilidade fundamental para DevOps, permitindo automatizar tarefas repetitivas como backups, deploy, monitoramento e configuração de servidores. Nesta aula, você aprenderá a criar scripts robustos, gerenciar variáveis de ambiente, agendar tarefas com cron e decidir quando usar shell ou ferramentas especializadas.

Dominar shell scripting aumenta sua produtividade e confiabilidade, já que scripts podem ser versionados, testados e reutilizados. Vamos explorar desde exemplos práticos até boas práticas de segurança e manutenção.

Scripts úteis

Scripts shell podem automatizar tarefas comuns do dia a dia, como backup de diretórios, monitoramento de logs, deploy de aplicações e limpeza de arquivos temporários. Eles são especialmente úteis em ambientes Unix/Linux, onde o shell é onipresente.

Exemplo: script de backup compactado com timestamp.

#!/bin/bash
# backup.sh - Backup de diretório com timestamp
BACKUP_DIR="/backups"
SOURCE_DIR="/var/www/html"
TIMESTAMP=$(date +"%Y%m%d_%H%M%S")
FILENAME="backup_${TIMESTAMP}.tar.gz"

echo "Iniciando backup de $SOURCE_DIR para $BACKUP_DIR/$FILENAME..."
tar -czf "$BACKUP_DIR/$FILENAME" "$SOURCE_DIR"

echo "Backup concluído: $BACKUP_DIR/$FILENAME"

Outro script útil é o monitor de espaço em disco, que envia alerta se a utilização exceder um limiar.

#!/bin/bash
# disk_monitor.sh - Alerta se uso de disco > 80%
THRESHOLD=80
USAGE=$(df / | tail -1 | awk '{print $5}' | sed 's/%//')

if [ "$USAGE" -gt "$THRESHOLD" ]; then
    echo "ALERTA: Uso de disco em / é ${USAGE}% (limite: ${THRESHOLD}%)" | mail -s "Alerta de Disco" admin@exemplo.com
fi

Variáveis de ambiente

Variáveis de ambiente são valores dinâmicos que influenciam o comportamento de processos no sistema. No shell, são acessadas com o prefixo $ e podem ser definidas no terminal ou em scripts. Exemplos comuns: PATH, HOME, USER. Para definir uma variável no script: VAR=valor (sem espaços). Para exportar para subprocessos: export VAR.

Boas práticas: use nomes em maiúsculas para variáveis de ambiente, evite sobrescrever variáveis do sistema, e utilize ${} para evitar ambiguidades. Exemplo de script que verifica se uma variável está definida:

#!/bin/bash
if [ -z "$DEPLOY_KEY" ]; then
    echo "Erro: DEPLOY_KEY não definida. Abortando."
    exit 1
fi
echo "Chave de deploy encontrada: ${DEPLOY_KEY:0:8}..."

Para listar todas as variáveis de ambiente, use env ou printenv. Variáveis podem ser passadas na execução de um comando: VAR=valor comando.

cron

O cron é um agendador de tarefas do Unix que executa scripts em intervalos definidos. A configuração é feita no arquivo crontab (acessado com crontab -e). Cada linha segue o formato: minuto hora dia mês semana comando.

Exemplos de agendamento:

  • 0 2 * * * /scripts/backup.sh – Executa diariamente às 2h.
  • */10 * * * * /scripts/disk_monitor.sh – A cada 10 minutos.
  • 0 0 1 * * /scripts/monthly_report.sh – Primeiro dia de cada mês à meia-noite.

Boas práticas: sempre usar caminhos absolutos, redirecionar saída para log (> /var/log/meu_script.log 2>&1), e testar o script manualmente antes de agendar. Cuidado com variáveis de ambiente: o cron executa com um ambiente mínimo; defina variáveis no próprio script ou no crontab.

Para listar tarefas do usuário: crontab -l. Para remover: crontab -r.

Quando usar shell vs ferramenta dedicada

Shell scripting é ideal para tarefas simples, rápidas e que envolvem comandos do sistema, como manipulação de arquivos, chamadas a APIs via curl, e integração com ferramentas CLI. No entanto, para tarefas complexas, como orquestração de vários serviços, deploy em múltiplos servidores, ou processamento de dados estruturados, ferramentas dedicadas são mais adequadas.

Exemplos de ferramentas: Ansible (automação de configuração), Terraform (infraestrutura como código), Jenkins (CI/CD), Python (scripts mais complexos). Use shell quando a tarefa for linear e depender de comandos Unix; use ferramentas dedicadas quando precisar de idempotência, paralelismo, ou gerenciamento de estado.

Regra prática: se seu script ultrapassar 50 linhas ou usar muitos if/else aninhados, considere migrar para Python ou uma ferramenta específica. Shell é frágil para lógica complexa e difícil de depurar.

Boas práticas

  • Use set -e para abortar em caso de erro, set -u para variáveis não definidas, e set -o pipefail para capturar falhas em pipes.
  • Valide entradas e saídas; nunca confie em dados externos.
  • Adicione cabeçalho com descrição e autor.
  • Utilize funções para modularizar código.
  • Mantenha scripts versionados em Git.

Referências

Exercícios

  1. Crie um script que faça backup de um diretório, compactando-o com tar e nomeando o arquivo com a data atual (YYYY-MM-DD). O script deve aceitar o diretório de origem como argumento.
  2. ✓ Resposta:
    #!/bin/bash
    if [ -z "$1" ]; then
        echo "Uso: $0 diretorio_origem"
        exit 1
    fi
    
    SOURCE="$1"
    DATE=$(date +"%Y-%m-%d")
    FILENAME="backup_${DATE}.tar.gz"
    tar -czf "$FILENAME" "$SOURCE"
    echo "Backup criado: $FILENAME"
    
  3. Escreva um script que verifique se uma variável de ambiente chamada DATABASE_URL está definida. Se não estiver, defina um valor padrão e exiba um aviso. Em seguida, exiba o valor final.
  4. ✓ Resposta:
    #!/bin/bash
    if [ -z "${DATABASE_URL+x}" ]; then
        echo "AVISO: DATABASE_URL não definida. Usando valor padrão."
        DATABASE_URL="postgres://localhost:5432/mydb"
    fi
    echo "DATABASE_URL=$DATABASE_URL"
    
  5. Agende um script de limpeza de logs (/scripts/clean_logs.sh) para executar todos os dias às 3h da manhã. Escreva a linha do crontab.
  6. ✓ Resposta:
    0 3 * * * /scripts/clean_logs.sh
    
  7. Explique em 2-3 frases quando você deve evitar usar shell script e preferir uma ferramenta como Ansible ou Python.
  8. ✓ Resposta:Evite shell scripts quando a lógica se torna complexa (muitas condições, loops aninhados), quando você precisa de idempotência (garantir estado final desejado) ou paralelismo. Ferramentas como Ansible oferecem módulos testados, gerenciamento de erros e idempotência; Python é melhor para manipulação de dados estruturados e integração com APIs.
  9. Escreva um script que liste todos os arquivos .log em /var/log que foram modificados nos últimos 7 dias e os compacte em um arquivo logs_old.tar.gz.
  10. ✓ Resposta:
    #!/bin/bash
    find /var/log -name "*.log" -mtime -7 -type f -print0 | xargs -0 tar -czf logs_old.tar.gz
    echo "Arquivos compactados em logs_old.tar.gz"