O shell scripting é uma habilidade fundamental para profissionais de DevOps, permitindo automatizar tarefas repetitivas, manipular arquivos, gerenciar processos e integrar ferramentas de forma rápida e eficiente. Nesta aula, exploraremos como criar scripts úteis no contexto de DevOps, gerenciar variáveis de ambiente, agendar execuções com cron e entender quando o shell é a melhor ferramenta ou quando é melhor optar por soluções mais robustas.

Dominar shell scripting não apenas acelera o trabalho diário, mas também é essencial para escrever pipelines de CI/CD, scripts de provisionamento e automação de infraestrutura. Vamos mergulhar em exemplos práticos e boas práticas.

Scripts úteis

No dia a dia de um DevOps, scripts shell podem automatizar desde backups e monitoramento até deploys e limpeza de logs. Um script bem escrito deve ser modular, reutilizável e robusto, tratando erros e fornecendo saídas claras.

Exemplo: Script para backup de diretório com compressão e logging.

#!/bin/bash
# backup.sh - Realiza backup de um diretório

BACKUP_DIR="/backups"
SOURCE_DIR="/var/www/html"
DATE=$(date +%Y%m%d_%H%M%S)
FILENAME="backup_$DATE.tar.gz"

# Criar diretório de backup se não existir
mkdir -p "$BACKUP_DIR"

# Realizar backup
tar -czf "$BACKUP_DIR/$FILENAME" "$SOURCE_DIR" 2>&1

# Verificar sucesso
if [ $? -eq 0 ]; then
    echo "Backup concluído: $FILENAME"
else
    echo "Erro no backup" >&2
    exit 1
fi

# Remover backups mais antigos que 7 dias
find "$BACKUP_DIR" -name "*.tar.gz" -mtime +7 -delete

Outro script útil é para monitoramento de recursos: verificar uso de disco e enviar alerta se acima do limite.

#!/bin/bash
# check_disk.sh - Alerta se uso de disco > 80%

THRESHOLD=80
CURRENT=$(df / | grep / | awk '{ print $5 }' | sed 's/%//g')

if [ "$CURRENT" -gt "$THRESHOLD" ]; then
    echo "Atenção: Uso de disco em $CURRENT%" | mail -s "Alerta de Disco" admin@example.com
fi

Variáveis de ambiente

Variáveis de ambiente são fundamentais para configurar scripts sem hardcodear valores sensíveis ou específicos do ambiente. Elas podem ser definidas no shell, em arquivos como .bashrc, .profile ou em arquivos específicos de aplicação.

No contexto DevOps, é comum usar variáveis de ambiente para armazenar credenciais, caminhos de diretórios, URLs de serviços e parâmetros de configuração. Exemplo:

#!/bin/bash
# deploy.sh - Usa variáveis de ambiente para deploy

# Defina antes: export APP_DIR="/opt/app"
# export DB_URL="postgres://user:pass@localhost:5432/mydb"

if [ -z "$APP_DIR" ]; then
    echo "APP_DIR não definida" >&2
    exit 1
fi

echo "Fazendo deploy para $APP_DIR"
cp -r ./* "$APP_DIR"
# ... outros comandos

Para tornar as variáveis persistentes, adicione-as ao ~/.bashrc ou use um arquivo .env e carregue com source .env. Cuidado: nunca versionar arquivos com senhas; use ferramentas como Vault ou secrets do CI/CD.

cron

O cron é o agendador de tarefas do Unix/Linux, permitindo executar scripts em intervalos definidos. Um arquivo crontab contém linhas com a especificação de tempo e o comando a ser executado.

Formato: minuto hora dia_mês mês dia_semana comando. Exemplo: executar backup todos os dias às 2h30:

30 2 * * * /home/user/scripts/backup.sh

Para editar o crontab: crontab -e. Listar: crontab -l. É importante redirecionar a saída para logs e tratar erros:

30 2 * * * /home/user/scripts/backup.sh >> /var/log/backup.log 2>&1

Dica: use cron para tarefas como rotação de logs, limpeza de arquivos temporários, verificações de saúde e atualizações automáticas. Mas evite tarefas muito frequentes (menos de 1 minuto) – para isso, use systemd timers ou ferramentas específicas.

Quando usar shell vs ferramenta dedicada

O shell scripting é excelente para tarefas simples, rápidas e que dependem de comandos Unix. Porém, para automações complexas, com lógica condicional extensa, manipulação de dados estruturados (JSON, YAML), ou que precisam de portabilidade entre sistemas, ferramentas como Python, Ansible ou Terraform são mais adequadas.

Critérios para escolha:

  • Shell: tarefas de uma linha, manipulação de arquivos, execução de comandos, integração rápida com pipelines CI/CD.
  • Python: scripts com lógica complexa, tratamento de exceções, bibliotecas para APIs, manipulação de dados.
  • Ansible: automação de configuração e gerenciamento de múltiplos servidores, idempotência.
  • Terraform: provisionamento de infraestrutura como código.

Exemplo: fazer uma requisição HTTP e processar JSON. Em shell, seria trabalhoso (usando curl e jq), enquanto em Python é mais legível e robusto. Use shell para glue code e ferramentas dedicadas para orquestração.

Boas práticas

Sempre comece scripts com #!/bin/bash e use set -e para parar em erros, set -u para variáveis não definidas. Comente o código, use nomes descritivos e evite códigos mágicos. Teste scripts em ambiente isolado antes de colocar em produção.

Referências

Exercícios

  1. Escreva um script que verifique se um diretório passado como argumento existe e, se não, crie-o.

    ✓ Resposta:
    #!/bin/bash
    if [ -d "$1" ]; then
        echo "Diretório $1 já existe."
    else
        mkdir -p "$1"
        echo "Diretório $1 criado."
    fi
  2. Crie um script que liste todos os processos de um usuário específico (fornecido como argumento) e mostre o PID e comando.

    ✓ Resposta:
    #!/bin/bash
    ps -u "$1" -o pid,comm --no-headers
  3. Escreva um script que use uma variável de ambiente para definir um diretório de logs e faça a rotação dos arquivos com mais de 7 dias (compacte e remova).

    ✓ Resposta:
    #!/bin/bash
    LOG_DIR="${LOG_DIR:-/var/log/myapp}"
    find "$LOG_DIR" -name "*.log" -mtime +7 -exec gzip {} \;
    find "$LOG_DIR" -name "*.log.gz" -mtime +30 -delete
  4. Configure um cron job (escreva a linha crontab) para executar um script de backup toda segunda-feira às 3h da manhã.

    ✓ Resposta:
    0 3 * * 1 /home/user/scripts/backup.sh
  5. Cite duas situações em que seria melhor usar Python em vez de shell script.

    ✓ Resposta:1. Quando é necessário processar dados JSON complexos ou fazer requisições HTTP com tratamento de erros. 2. Quando o script precisa ser multiplataforma (Windows, Linux, macOS) com o mesmo código.