Scripts Úteis para Redes
Coleção de scripts comentados em português, prontos para uso em ambientes de ISP e redes corporativas.
Pré-requisitos gerais
- Bash:
openssh-client,snmp,snmp-mibs-downloader - Python:
pysnmp(pip install pysnmp) - MikroTik: RouterOS 6.49+ ou 7.x
1. Bash — Backup automático de roteadores via SSH
Realiza backup de configuração de uma lista de roteadores via SSH, salvando com timestamp e mantendo os últimos 7 arquivos por equipamento.
#!/bin/bash
# backup-roteadores.sh
# Backup automático de configuração via SSH (Huawei / MikroTik / Linux)
# Uso: ./backup-roteadores.sh
# Agendar via cron: 0 2 * * * /opt/scripts/backup-roteadores.sh
# --- Configuração ---
BACKUP_DIR="/opt/backups/roteadores"
LOG_FILE="/var/log/backup-roteadores.log"
SSH_USER="backup"
SSH_KEY="/home/backup/.ssh/id_rsa"
RETENTION_DAYS=7 # Manter backups dos últimos 7 dias
# Lista de equipamentos: "hostname:ip:tipo"
# Tipos suportados: huawei | mikrotik
EQUIPAMENTOS=(
"core-sp1:10.0.0.1:huawei"
"core-sp2:10.0.0.2:huawei"
"bng-01:10.0.0.10:huawei"
"mk-borda:10.0.1.1:mikrotik"
)
# --- Funções ---
log() {
echo "[$(date '+%Y-%m-%d %H:%M:%S')] $1" | tee -a "$LOG_FILE"
}
backup_huawei() {
local hostname=$1
local ip=$2
local arquivo="${BACKUP_DIR}/${hostname}_$(date +%Y%m%d_%H%M%S).cfg"
# Huawei VRP: exibe a configuração atual e salva localmente
ssh -i "$SSH_KEY" \
-o StrictHostKeyChecking=no \
-o ConnectTimeout=15 \
-o BatchMode=yes \
"${SSH_USER}@${ip}" \
"display current-configuration" > "$arquivo" 2>/dev/null
if [ $? -eq 0 ] && [ -s "$arquivo" ]; then
log "OK | $hostname ($ip) | $(wc -l < "$arquivo") linhas | $arquivo"
else
log "ERRO| $hostname ($ip) | Falha na conexão ou arquivo vazio"
rm -f "$arquivo"
return 1
fi
}
backup_mikrotik() {
local hostname=$1
local ip=$2
local arquivo="${BACKUP_DIR}/${hostname}_$(date +%Y%m%d_%H%M%S).rsc"
# MikroTik RouterOS: exporta configuração em texto
ssh -i "$SSH_KEY" \
-o StrictHostKeyChecking=no \
-o ConnectTimeout=15 \
-o BatchMode=yes \
"${SSH_USER}@${ip}" \
"/export" > "$arquivo" 2>/dev/null
if [ $? -eq 0 ] && [ -s "$arquivo" ]; then
log "OK | $hostname ($ip) | $(wc -l < "$arquivo") linhas | $arquivo"
else
log "ERRO| $hostname ($ip) | Falha na conexão ou arquivo vazio"
rm -f "$arquivo"
return 1
fi
}
# --- Principal ---
mkdir -p "$BACKUP_DIR"
log "=== Início do ciclo de backup ==="
SUCESSO=0
FALHA=0
for equip in "${EQUIPAMENTOS[@]}"; do
IFS=':' read -r hostname ip tipo <<< "$equip"
case "$tipo" in
huawei) backup_huawei "$hostname" "$ip" && ((SUCESSO++)) || ((FALHA++)) ;;
mikrotik) backup_mikrotik "$hostname" "$ip" && ((SUCESSO++)) || ((FALHA++)) ;;
*) log "AVISO| $hostname | Tipo desconhecido: $tipo" ;;
esac
done
# Remover backups antigos (mais de RETENTION_DAYS dias)
find "$BACKUP_DIR" -name "*.cfg" -o -name "*.rsc" | \
xargs ls -t 2>/dev/null | \
awk -v keep="$((${#EQUIPAMENTOS[@]} * RETENTION_DAYS))" 'NR > keep {print}' | \
xargs rm -f 2>/dev/null
log "=== Fim do ciclo | Sucesso: $SUCESSO | Falha: $FALHA ==="2. Bash — Ping sweep de sub-rede
Varre uma sub-rede /24 enviando um ping por host e exibe quais estão respondendo, com resolução de hostname reverso.
#!/bin/bash
# ping-sweep.sh
# Uso: ./ping-sweep.sh 192.168.1
# Exemplo: ./ping-sweep.sh 10.0.0 (varre 10.0.0.1 a 10.0.0.254)
REDE=${1:-"192.168.1"} # Prefixo /24 sem o último octeto
TIMEOUT=1 # Segundos de timeout por ping
PARALELO=50 # Quantidade de pings simultâneos
if [[ -z "$1" ]]; then
echo "Uso: $0 <prefixo-rede>"
echo "Exemplo: $0 192.168.1"
exit 1
fi
echo "Varrendo ${REDE}.1 a ${REDE}.254 ..."
echo "--------------------------------------"
# Função de ping individual (chamada em background)
verifica_host() {
local ip="${REDE}.${1}"
if ping -c1 -W"$TIMEOUT" "$ip" &>/dev/null; then
# Tentar resolução reversa (PTR)
hostname=$(dig +short -x "$ip" 2>/dev/null | sed 's/\.$//')
if [[ -n "$hostname" ]]; then
printf "%-18s ONLINE %s\n" "$ip" "$hostname"
else
printf "%-18s ONLINE\n" "$ip"
fi
fi
}
export -f verifica_host
export REDE TIMEOUT
# Executa em paralelo usando xargs
seq 1 254 | xargs -P "$PARALELO" -I{} bash -c 'verifica_host "$@"' _ {}
echo "--------------------------------------"
echo "Varredura concluída."3. Bash — Monitor de interfaces via SNMP (loop contínuo)
Monitora o status e o tráfego de interfaces de um equipamento via SNMP, exibindo atualizações a cada intervalo definido. Útil para acompanhar em tempo real durante um incidente.
#!/bin/bash
# monitor-interfaces-snmp.sh
# Monitora interfaces de um equipamento via SNMPv2c
# Uso: ./monitor-interfaces-snmp.sh <ip> <community> [intervalo_segundos]
# Exemplo: ./monitor-interfaces-snmp.sh 10.0.0.1 public 5
IP=${1:?"Informe o IP do equipamento"}
COMMUNITY=${2:?"Informe a community SNMP"}
INTERVALO=${3:-5} # Segundos entre cada leitura (padrão: 5)
# OIDs padrão (IF-MIB — RFC 2863)
OID_IFNAME="1.3.6.1.2.1.31.1.1.1.1" # ifName
OID_IFOPERSTATUS="1.3.6.1.2.1.2.2.1.8" # ifOperStatus (1=up, 2=down)
OID_IFINOCTETS="1.3.6.1.2.1.31.1.1.1.6" # ifHCInOctets (64-bit)
OID_IFOUTOCTETS="1.3.6.1.2.1.31.1.1.1.10" # ifHCOutOctets (64-bit)
# Verificar dependência
if ! command -v snmpwalk &>/dev/null; then
echo "Erro: snmpwalk não encontrado. Instale com: apt install snmp"
exit 1
fi
echo "Monitor SNMP — $IP (community: $COMMUNITY) — intervalo: ${INTERVALO}s"
echo "Pressione Ctrl+C para parar."
echo ""
# Capturar valores anteriores para calcular taxa (bps)
declare -A prev_in prev_out prev_time
while true; do
clear
NOW=$(date '+%Y-%m-%d %H:%M:%S')
echo "=== $IP | $NOW ==="
printf "%-30s %-8s %15s %15s\n" "Interface" "Status" "RX (Mbps)" "TX (Mbps)"
echo "------------------------------------------------------------------------"
# Ler nomes das interfaces
while IFS= read -r line; do
idx=$(echo "$line" | grep -oP '\.\K[0-9]+(?= =)')
name=$(echo "$line" | grep -oP '".*"' | tr -d '"')
[ -z "$idx" ] && continue
# Status da interface
status_raw=$(snmpget -v2c -c "$COMMUNITY" -Oqv "${IP}" "${OID_IFOPERSTATUS}.${idx}" 2>/dev/null)
status="unknown"
[[ "$status_raw" == "1" ]] && status="up"
[[ "$status_raw" == "2" ]] && status="DOWN"
# Octetos acumulados
in_now=$(snmpget -v2c -c "$COMMUNITY" -Oqv "${IP}" "${OID_IFINOCTETS}.${idx}" 2>/dev/null)
out_now=$(snmpget -v2c -c "$COMMUNITY" -Oqv "${IP}" "${OID_IFOUTOCTETS}.${idx}" 2>/dev/null)
time_now=$(date +%s%3N) # milissegundos
rx_mbps="-"
tx_mbps="-"
# Calcular taxa se tivermos valor anterior
if [[ -n "${prev_in[$idx]}" && -n "$in_now" && "$in_now" =~ ^[0-9]+$ ]]; then
delta_t=$(( (time_now - prev_time[$idx]) ))
[ "$delta_t" -gt 0 ] && {
delta_in=$(( (in_now - prev_in[$idx]) * 8 ))
delta_out=$(( (out_now - prev_out[$idx]) * 8 ))
rx_mbps=$(echo "scale=2; $delta_in / $delta_t / 1000" | bc 2>/dev/null)
tx_mbps=$(echo "scale=2; $delta_out / $delta_t / 1000" | bc 2>/dev/null)
}
fi
# Salvar valores atuais para próximo ciclo
prev_in[$idx]=$in_now
prev_out[$idx]=$out_now
prev_time[$idx]=$time_now
printf "%-30s %-8s %15s %15s\n" "$name" "$status" "$rx_mbps" "$tx_mbps"
done < <(snmpwalk -v2c -c "$COMMUNITY" -Oq "${IP}" "${OID_IFNAME}" 2>/dev/null)
sleep "$INTERVALO"
done4. Python — Verificar sessões BGP via SNMP
Consulta as sessões BGP de um roteador via SNMP (BGP4-MIB) e exibe o estado de cada peer, ASN remoto e prefixos aceitos.
#!/usr/bin/env python3
# bgp-snmp-check.py
# Verifica sessões BGP via SNMPv2c (BGP4-MIB — RFC 4273)
# Uso: python3 bgp-snmp-check.py <ip> <community>
# Dependência: pip install pysnmp
import sys
from pysnmp.hlapi import (
SnmpEngine, CommunityData, UdpTransportTarget,
ContextData, ObjectType, ObjectIdentity,
nextCmd, getCmd
)
# OIDs da BGP4-MIB
BGP_PEER_STATE = "1.3.6.1.2.1.15.3.1.2" # bgpPeerState
BGP_PEER_REMOTE_AS = "1.3.6.1.2.1.15.3.1.9" # bgpPeerRemoteAs
BGP_PEER_IN_PREFIXES = "1.3.6.1.2.1.15.3.1.11" # bgpPeerInTotalMessages (aprox)
BGP_PEER_ACCEPTED = "1.3.6.1.2.1.15.3.1.23" # bgpPeerInUpdateElapsedTime
BGP_LOCAL_AS = "1.3.6.1.2.1.15.2.0" # bgpLocalAs
# Mapeamento de estado numérico para texto
ESTADOS_BGP = {
1: "idle",
2: "connect",
3: "active",
4: "opensent",
5: "openconfirm",
6: "established",
}
def snmp_walk(host, community, oid):
"""Retorna um dicionário {sufixo_oid: valor} para um OID base."""
resultados = {}
for (errorIndication, errorStatus, errorIndex, varBinds) in nextCmd(
SnmpEngine(),
CommunityData(community, mpModel=1), # v2c
UdpTransportTarget((host, 161), timeout=3, retries=2),
ContextData(),
ObjectType(ObjectIdentity(oid)),
lexicographicMode=False
):
if errorIndication or errorStatus:
break
for varBind in varBinds:
oid_str = str(varBind[0])
valor = str(varBind[1])
# Extrair sufixo (endereço IP do peer)
sufixo = oid_str.replace(oid + ".", "")
resultados[sufixo] = valor
return resultados
def snmp_get(host, community, oid):
"""Retorna o valor de um OID escalar."""
for (errorIndication, errorStatus, _, varBinds) in getCmd(
SnmpEngine(),
CommunityData(community, mpModel=1),
UdpTransportTarget((host, 161), timeout=3, retries=2),
ContextData(),
ObjectType(ObjectIdentity(oid)),
):
if errorIndication or errorStatus:
return None
return str(varBinds[0][1])
return None
def main():
if len(sys.argv) < 3:
print(f"Uso: {sys.argv[0]} <ip> <community>")
sys.exit(1)
host = sys.argv[1]
community = sys.argv[2]
print(f"\n=== BGP Peers — {host} ===")
# AS local
local_as = snmp_get(host, community, BGP_LOCAL_AS)
print(f"AS Local: {local_as or 'não disponível'}\n")
# Coletar dados dos peers
estados = snmp_walk(host, community, BGP_PEER_STATE)
remote_as = snmp_walk(host, community, BGP_PEER_REMOTE_AS)
if not estados:
print("Nenhum peer BGP encontrado (verifique community e acesso SNMP).")
sys.exit(1)
print(f"{'Peer IP':<18} {'AS Remoto':<12} {'Estado':<14} {'Alerta'}")
print("-" * 65)
estabelecidos = 0
problemas = 0
for peer_ip, estado_num in sorted(estados.items()):
estado_int = int(estado_num) if estado_num.isdigit() else 0
estado_str = ESTADOS_BGP.get(estado_int, f"desconhecido({estado_num})")
as_remoto = remote_as.get(peer_ip, "?")
# Sinalizar peers não estabelecidos
alerta = ""
if estado_int == 6:
estabelecidos += 1
else:
alerta = "<<< ATENÇÃO"
problemas += 1
print(f"{peer_ip:<18} {as_remoto:<12} {estado_str:<14} {alerta}")
print("-" * 65)
print(f"\nResumo: {estabelecidos} established | {problemas} com problema\n")
# Código de saída útil para monitoramento (Zabbix external check, etc.)
sys.exit(0 if problemas == 0 else 2)
if __name__ == "__main__":
main()Exemplo de saída:
=== BGP Peers — 10.0.0.1 ===
AS Local: 65001
Peer IP AS Remoto Estado Alerta
-----------------------------------------------------------------
10.0.0.2 65002 established
192.168.100.1 6762 established
203.0.113.1 1234 active <<< ATENÇÃO
-----------------------------------------------------------------
Resumo: 2 established | 1 com problema5. MikroTik RouterOS — Script de backup automático
Script nativo RouterOS que gera um backup binário e um export de texto, salva localmente e envia por e-mail (opcional).
# mikrotik-backup.rsc
# Script de backup automático para MikroTik RouterOS
# Como usar:
# 1. Cole em System > Scripts > Name: "backup-diario"
# 2. Agende em System > Scheduler:
# Name: backup-diario | Start Time: 02:00:00 | Interval: 1d
# On Event: backup-diario
# --- Configuração ---
:local nomeHost [/system identity get name]
:local dataHora [/system clock get date]
:local hora [/system clock get time]
# Formatar data para nome de arquivo (remove "/" e ":")
:local data [:pick $dataHoje 7 11]
:set dataHora ($nomeHost . "_" . \
[:pick $dataHora 7 11] . \
[:pick $dataHora 3 5] . \
[:pick $dataHora 0 2])
# --- Gerar arquivos de backup ---
# 1. Backup binário (inclui senhas — protegido por senha)
/system backup save \
name=($dataHora . "_bin") \
password="SenhaForteAqui123"
# 2. Export de texto (sem senhas, mas legível)
/export \
file=($dataHora . "_export") \
hide-sensitive
:log info ("Backup gerado: " . $dataHora)
# --- Remover backups antigos (manter últimos 5) ---
:local arquivos [/file find name~"_bin.backup"]
:local total [:len $arquivos]
:if ($total > 5) do={
:local remover ($total - 5)
:for i from=0 to=($remover - 1) do={
:local arquivo [:pick $arquivos $i]
/file remove [/file find name=[/file get $arquivo name]]
:log info "Backup antigo removido"
}
}
# --- Enviar por e-mail (opcional — requer /tool e-mail configurado) ---
# Descomente as linhas abaixo se tiver SMTP configurado:
# /tool e-mail send \
# to="noc@empresa.com.br" \
# subject=("Backup RouterOS - " . $nomeHost . " - " . $dataHora) \
# body=("Backup automático gerado com sucesso.\nEquipamento: " . $nomeHost) \
# file=($dataHora . "_export.rsc")
:log info "Script de backup concluído com sucesso."6. Bash — Verificar sinal óptico de ONUs via SNMP Huawei
Consulta o sinal óptico (RX/TX em dBm) de todas as ONUs de uma OLT Huawei MA5800 via SNMP, alertando para valores fora do padrão.
#!/bin/bash
# sinal-onus-huawei.sh
# Consulta sinal óptico de ONUs em OLT Huawei via SNMP
# Uso: ./sinal-onus-huawei.sh <ip-olt> <community>
# Dependência: apt install snmp
IP_OLT=${1:?"Informe o IP da OLT"}
COMMUNITY=${2:?"Informe a community SNMP"}
# Limiares de sinal (dBm × 100 como inteiro, conforme a MIB Huawei)
# A MIB Huawei retorna valores em unidades de 0.01 dBm (ex: -2250 = -22.50 dBm)
LIMITE_CRITICO=-2800 # < -28.00 dBm = offline iminente
LIMITE_ATENCAO=-2700 # < -27.00 dBm = sinal fraco
# OIDs Huawei GPON (hwGponDeviceMIB — compatível com MA5800 VRP V800R021+)
OID_ONT_SINAL_RX="1.3.6.1.4.1.2011.6.128.1.1.2.51.1.4" # hwGponOntOpticalRxPower
OID_ONT_DESCRICAO="1.3.6.1.4.1.2011.6.128.1.1.2.46.1.10" # hwGponOntDescrip
if ! command -v snmpwalk &>/dev/null; then
echo "Erro: snmpwalk não encontrado. Instale: apt install snmp"
exit 1
fi
echo "=== Sinal Óptico ONUs — OLT $IP_OLT ==="
echo "$(date '+%Y-%m-%d %H:%M:%S')"
echo ""
printf "%-25s %-10s %-10s %-10s\n" "OID Índice" "RX (dBm)" "Status" "Alerta"
echo "------------------------------------------------------------"
CRITICO=0
ATENCAO=0
NORMAL=0
# Coletar sinais RX
while IFS= read -r linha; do
# Extrair índice e valor
idx=$(echo "$linha" | grep -oP '\.\K[\d.]+(?= =)')
valor_raw=$(echo "$linha" | grep -oP '= \K-?[0-9]+')
[ -z "$valor_raw" ] && continue
# Converter para dBm com duas casas decimais
dbm=$(echo "scale=2; $valor_raw / 100" | bc 2>/dev/null)
# Classificar sinal
alerta=""
status=""
if [ "$valor_raw" -lt "$LIMITE_CRITICO" ]; then
status="CRITICO"
alerta=">>> SINAL CRITICO"
((CRITICO++))
elif [ "$valor_raw" -lt "$LIMITE_ATENCAO" ]; then
status="ATENCAO"
alerta="> sinal fraco"
((ATENCAO++))
else
status="ok"
((NORMAL++))
fi
printf "%-25s %-10s %-10s %s\n" "$idx" "${dbm} dBm" "$status" "$alerta"
done < <(snmpwalk -v2c -c "$COMMUNITY" -Oq "$IP_OLT" "$OID_ONT_SINAL_RX" 2>/dev/null)
echo "------------------------------------------------------------"
echo "Resumo: $NORMAL ok | $ATENCAO atenção | $CRITICO crítico"
echo ""
# Código de saída para uso com Zabbix / Nagios
[ "$CRITICO" -gt 0 ] && exit 2
[ "$ATENCAO" -gt 0 ] && exit 1
exit 0Integração com Zabbix
Os scripts Python e Bash com código de saída 0/1/2 podem ser usados como external checks no Zabbix. Salve em /usr/lib/zabbix/externalscripts/ e configure um item do tipo "External check" no host.