O monitoramento de sistemas é uma tarefa essencial para garantir a disponibilidade e a saúde de servidores e serviços. Scripts de monitoramento automatizam a verificação de recursos críticos, como serviços ativos, espaço em disco, uso de CPU e memória, e podem enviar alertas quando algo sai do esperado. Nesta aula, vamos explorar como criar scripts de monitoramento em Bash, desde a verificação de serviços até o agendamento dessas verificações.

Vamos abordar quatro áreas principais: checagem de serviços, uso de disco, alertas (por e-mail e log) e agendamento com cron. Ao final, você terá um repertório de técnicas para construir seus próprios scripts de monitoramento, com foco em robustez e boas práticas.

Checando serviços

Verificar se um serviço está ativo é uma das tarefas mais comuns em monitoramento. No Linux, podemos usar comandos como systemctl (para sistemas com systemd) ou service (para SysV init). O comando systemctl is-active retorna o status de um serviço de forma simples.

Em um script, podemos capturar o status e agir de acordo. Por exemplo, se um serviço crítico estiver inativo, podemos tentar reiniciá-lo ou enviar um alerta. Vamos ver um exemplo:

#!/bin/bash
# Script para verificar se o serviço nginx está ativo

SERVICE="nginx"

if systemctl is-active --quiet "$SERVICE"; then
    echo "O serviço $SERVICE está ativo."
else
    echo "O serviço $SERVICE está INATIVO!"
    # Tenta reiniciar
    systemctl restart "$SERVICE"
    if systemctl is-active --quiet "$SERVICE"; then
        echo "Serviço reiniciado com sucesso."
    else
        echo "Falha ao reiniciar o serviço."
    fi
fi

Neste script, usamos systemctl is-active --quiet que não produz saída, apenas retorna o código de saída (0 se ativo, não-zero se inativo). Isso é útil para testes condicionais. Também podemos verificar múltiplos serviços em um loop, armazenando os nomes em um array.

#!/bin/bash
# Verifica múltiplos serviços

SERVICES=("nginx" "mysql" "docker")

for svc in "${SERVICES[@]}"; do
    if systemctl is-active --quiet "$svc"; then
        echo "$svc: ativo"
    else
        echo "$svc: INATIVO"
    fi
done

É importante considerar que alguns serviços podem usar nomes diferentes do nome do processo. Verifique com systemctl list-units --type=service para ver os nomes corretos.

Uso de disco

O monitoramento do uso de disco é crucial para evitar que partições fiquem cheias, o que pode causar falhas em aplicações. O comando df mostra o uso de disco, e podemos analisar a saída para extrair a porcentagem de uso.

Um script pode verificar se a utilização de uma partição ultrapassou um limite (por exemplo, 80%) e então disparar um alerta. Vamos ver como fazer isso:

#!/bin/bash
# Verifica o uso de disco da raiz

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

if [ "$CURRENT" -gt "$THRESHOLD" ]; then
    echo "Alerta: uso de disco em / é ${CURRENT}% (limite: ${THRESHOLD}%)"
else
    echo "Uso de disco em / é ${CURRENT}% (dentro do limite)."
fi

O comando df / mostra a linha da partição raiz, e com awk extraímos o quinto campo (a porcentagem), e com sed removemos o símbolo de porcentagem. Podemos generalizar para verificar várias partições, usando df -h e iterando sobre as linhas.

#!/bin/bash
# Verifica todas as partições montadas

THRESHOLD=80

df -h | tail -n +2 | while read line; do
    # Extrai o ponto de montagem e a porcentagem
    mount=$(echo "$line" | awk '{print $6}')
    usage=$(echo "$line" | awk '{print $5}' | sed 's/%//')
    if [ "$usage" -gt "$THRESHOLD" ]; then
        echo "Alerta: partição $mount está com ${usage}% de uso."
    fi
done

Neste exemplo, usamos tail -n +2 para pular o cabeçalho, e para cada linha extraímos o ponto de montagem (campo 6) e a porcentagem (campo 5). Note que a ordenação dos campos pode variar com as opções do df; verifique com df -h.

Uma alternativa mais robusta é usar o comando findmnt ou ler o arquivo /proc/mounts, mas para scripts simples, df é suficiente.

Alertas (e-mail/log)

Quando um problema é detectado, é essencial notificar o administrador. Duas formas comuns são enviar e-mail e registrar em arquivos de log. O envio de e-mail pode ser feito com o comando mail ou sendmail, mas é necessário um servidor de e-mail configurado ou um serviço externo. Para esta aula, usaremos o comando mail (pacote mailutils ou bsd-mailx).

Exemplo de envio de e-mail:

#!/bin/bash
# Envia um e-mail de alerta

EMAIL="admin@example.com"
SUBJECT="Alerta de monitoramento"
BODY="Problema detectado no servidor."

echo "$BODY" | mail -s "$SUBJECT" "$EMAIL"

Também podemos usar sendmail para maior controle, mas mail é mais simples.

Além do e-mail, registrar eventos em um arquivo de log é uma prática recomendada. Podemos usar logger para enviar mensagens ao syslog, ou simplesmente redirecionar a saída para um arquivo. Exemplo:

#!/bin/bash
# Registra alerta em arquivo de log

LOG_FILE="/var/log/monitor.log"
echo "$(date '+%Y-%m-%d %H:%M:%S') - Alerta: uso de disco acima do limite" >> "$LOG_FILE"

Em scripts de monitoramento, é comum combinar e-mail e log. Vamos criar uma função para enviar alertas que registra no log e envia e-mail:

#!/bin/bash

LOG_FILE="/var/log/monitor.log"
EMAIL="admin@example.com"

send_alert() {
    local MESSAGE="$1"
    echo "$(date '+%Y-%m-%d %H:%M:%S') - $MESSAGE" >> "$LOG_FILE"
    echo "$MESSAGE" | mail -s "[Monitor] Alerta" "$EMAIL"
}

# Uso
send_alert "Disco cheio!"

Lembre-se de que o comando mail pode exigir configurações adicionais, como um relay. Em servidores de produção, é comum usar um serviço de e-mail transacional ou um script de envio via API.

Agendamento

Para que os scripts de monitoramento sejam executados periodicamente, usamos o cron, o agendador de tarefas do Linux. O cron lê arquivos de configuração (crontab) e executa comandos nos horários especificados.

Para editar o crontab do usuário atual, use crontab -e. A sintaxe básica é: minuto hora dia-do-mês mês dia-da-semana comando. Por exemplo, para executar o script a cada 5 minutos:

*/5 * * * * /caminho/para/script.sh

Se o script precisar de permissões de root, edite o crontab do root (sudo crontab -e).

Um cuidado importante: scripts executados pelo cron não têm o mesmo ambiente que o shell interativo. Por isso, é recomendável usar caminhos absolutos para comandos e definir variáveis de ambiente, como PATH, no início do script.

Exemplo de crontab para monitorar a cada 10 minutos e enviar alertas:

# Edite com crontab -e
*/10 * * * * /usr/local/bin/monitor.sh

Também podemos usar systemd timers como uma alternativa mais moderna, mas o cron ainda é amplamente utilizado. Para agendar tarefas mais complexas, como a cada hora em um dia específico, consulte a documentação do cron.

Uma dica: teste o script manualmente antes de agendar, e verifique os logs do cron (/var/log/syslog ou /var/log/cron) para garantir que está sendo executado.

Boas práticas

Ao criar scripts de monitoramento, siga estas boas práticas:

  • Use caminhos absolutos para comandos e arquivos, especialmente quando executado pelo cron.
  • Defina variáveis de ambiente no início do script, como PATH.
  • Trate erros com set -e ou verificação de códigos de saída.
  • Use funções para organizar o código e evitar repetição.
  • Registre todas as ações em logs para facilitar a depuração.
  • Teste exaustivamente antes de colocar em produção.

Referências

Exercícios

  1. Exercício 1: Escreva um script que verifique se o serviço sshd está ativo e, se não estiver, tente iniciá-lo e exiba uma mensagem de sucesso ou falha.
  2. ✓ Resposta:
    #!/bin/bash
    SERVICE="sshd"
    if systemctl is-active --quiet "$SERVICE"; then
        echo "O serviço $SERVICE já está ativo."
    else
        echo "O serviço $SERVICE está inativo. Tentando iniciar..."
        systemctl start "$SERVICE"
        if systemctl is-active --quiet "$SERVICE"; then
            echo "Serviço iniciado com sucesso."
        else
            echo "Falha ao iniciar o serviço."
        fi
    fi
    
  3. Exercício 2: Crie um script que monitore o uso de disco da partição /home, alertando se a utilização for maior que 90%. Use o comando df e awk.
  4. ✓ Resposta:
    #!/bin/bash
    THRESHOLD=90
    CURRENT=$(df /home | awk 'NR==2 {print $5}' | sed 's/%//')
    if [ "$CURRENT" -gt "$THRESHOLD" ]; then
        echo "ALERTA: Uso de disco em /home é ${CURRENT}% (limite: ${THRESHOLD}%)"
    else
        echo "Uso de disco em /home é ${CURRENT}% (dentro do limite)."
    fi
    
  5. Exercício 3: Escreva um script que envie um e-mail de alerta e registre em um log quando o uso de memória ultrapassar 80%. Use o comando free para obter o uso.
  6. ✓ Resposta:
    #!/bin/bash
    THRESHOLD=80
    MEM_USAGE=$(free | awk '/Mem:/ {printf "%.0f", $3/$2 * 100}')
    if [ "$MEM_USAGE" -gt "$THRESHOLD" ]; then
        MESSAGE="Uso de memória em ${MEM_USAGE}%"
        echo "$(date '+%Y-%m-%d %H:%M:%S') - $MESSAGE" >> /var/log/monitor.log
        echo "$MESSAGE" | mail -s "[Monitor] Alerta de memória" admin@example.com
    fi
    
  7. Exercício 4: Agende o script do Exercício 2 para executar a cada 5 minutos usando cron. Mostre a linha do crontab.
  8. ✓ Resposta:
    */5 * * * * /caminho/para/script.sh
    
  9. Exercício 5: Crie um script que verifique se uma lista de serviços (por exemplo, nginx, mysql, docker) está ativa e envie um alerta por e-mail para cada serviço inativo. Use um loop.
  10. ✓ Resposta:
    #!/bin/bash
    SERVICES=("nginx" "mysql" "docker")
    EMAIL="admin@example.com"
    for svc in "${SERVICES[@]}"; do
        if ! systemctl is-active --quiet "$svc"; then
            echo "O serviço $svc está inativo." | mail -s "Alerta: serviço $svc" "$EMAIL"
        fi
    done