Eis o conteúdo do script "astnagios.sh":
#!/bin/sh
#crio variáveis necessárias
nome=$(date +%m%d%H%M%S)
workdir=/opt/scripts/astnagios
date > $workdir/data
minutodate=$(date +%s)
#Pode acontecer um efeito cascata, ou seja, a queda de um switch, que possui outros ligados nele,
#o que pode ocasionar várias ligações. Detecto e trato isso da seguinte forma:
#insiro a data, em segundos, desde 01 de janeiro de 1970, no arquivo minutocontroler, ou seja, cada
#vez que o script é executado, ele insere a data no arquivo minutocontroler
echo $minutodate >> $workdir/minutocontroler
#capturo as últimas 10 linhas do arquivo minutocontroler, e as insiro no arquivo checkidade
tail -n 10 $workdir/minutocontroler > $workdir/checkidade
#crio as variaveis minuto1 e minuto2, e apago o arquivo checkidade
minuto1=$(head -1 $workdir/checkidade)
minuto2=$(tail -1 $workdir/checkidade)
rm $workdir/checkidade
#pego o momento da ultima execução, subtraio o momento da primeira execução, e insiro o
#resultado no arquivo acompanhacascata
let "idademinuto=(($minuto2 - $minuto1))"
echo $idademinuto >> $workdir/acompanhacascata
#caso o resultado seja menor do que 150 segundos, isso significa que caíram 10 hosts em menos de
#1 minuto e meio, o que, obviamente, é uma cascata
#então, entra o tratamento
if [ $idademinuto -le 150 ]; then
#insiro as palavras CASCATA DETECTADA, no arquivo cascata, que possui apenas 1 linha, em #branco
echo "CASCATA DETECTADA" >> $workdir/cascata
#conto o número de linhas do arquivo cascata
linhascascata=$(grep -c "" $workdir/cascata)
#se o número de linhas for igual a 2, significa que foi detectada uma
#cascata, por isso o arquivo foi incrementado
if [ $linhascascata == 2 ]; then
#nesse caso, envio arquivos .call que executam um arquivo de áudio
#que diz: "cascata detectada, as #ligações serão interrompidas" para o
#servidor asterisk (essa é a mensagem de áudio que os responsáveis receberão).
scp $workdir/cascatafiles/*.cascata 192.168.0.228:/var/spool/asterisk/outgoing
#se o número de linhas do arquivo de cascata for diferente de 2, maior,
#obviamente, incrementamos um log, apenas a título de controle posterior.
datah=$(cat $workdir/data)
echo $datah AVISO DE CASCATA >> $workdir/logcascata
fi
else
#se nao houver cascata
#faz o arquivo cascata voltar a ter apenas 1 linha vazia.
echo > $workdir/cascata
#crio a variável numcel, contendo a informação do arquivo numcel,
#que foi criado pelo nagios, inserindo nesse arquivo o conteúdo da variável $CONTACTPAGER
numcel=$(cat $workdir/numcel)
#crio a variável canal, contendo o número 1
canal=1
#caso exista o arquivo hostiden, trata-se de host, entao....
if [ -f $workdir/hostiden ];then
#identifica o nome do host e o status (up ou down)
hostiden=$(cat $workdir/hostiden);
hoststate=$(cat $workdir/hoststate);
#caso host up
if [ "$hoststate" == UP ]; then
sed -e s/destinatario/0$numcel/g -e s/i1/g$canal/g $workdir/calls/template."$hostiden".UP.call > $workdir/calls/"$nome.$hostiden".UP.call
scp $workdir/calls/"$nome.$hostiden".UP.call IPDOASTERISK:/var/spool/asterisk/outgoing
rm $workdir/calls/"$nome.$hostiden".UP.call
datah=$(cat $workdir/data)
echo $datah LIGACAO $hostiden UP EFETUADA PARA $numcel >> $workdir/logcalls
else
#caso host down
if [ "$hoststate" == DOWN ]; then
numcel=$(cat $workdir/numcel)
sed -e s/destinatario/0$numcel/g -e s/i1/g$canal/g $workdir/calls/template."$hostiden".DOWN.call > $workdir/calls/"$nome.$hostiden".DOWN.call
scp $workdir/calls/"$nome.$hostiden".DOWN.call IPDOASTERISK:/var/spool/asterisk/outgoing
rm $workdir/calls/"$nome.$hostiden".DOWN.call
datah=$(cat $workdir/data)
echo $datah LIGACAO $hostiden DOWN EFETUADA PARA $numcel >> $workdir/logcalls
fi
fi
fi
else
#apaga o lixo
rm $workdir/data
rm $workdir/hostiden
rm $workdir/hoststate
rm $workdir/numcel
fi
Explicações adicionais
Este é, portanto, o script que é executado no fim da linha do arquivo
commands.cfg. Tenho, dentro da pasta
/opt/scripts/astnagios uma subpasta chamada "calls", que contém, para cada host monitorado, dois arquivos:
- template.NOMEDOHOSTNONAGIOS.DOWN.call
- template.NOMEDOHOSTNONAGIOS.UP.call
Estes arquivos são copiados para um novo arquivo cujo nome se inicia com a data e hora em segundos (variável $nome, primeira criada no script,(nome=$(date +%m%d%H%M%S)), seguida do nome do host, estado e extensão ".call". Exemplo: 1112103026.SERVIDOREMAIL.UP.call, e editados via
sed quando o script é executado, substituindo a palavra "destinatario" pelo número de celular do destinatário, e o campo "I1" pelo canal desejado.
Este é o conteúdo original do arquivo
template.SERVIDOREMAIL.UP.call:
Channel:DAHDI/I1/destinatario
Application: MP3Player
Data: /var/lib/asterisk/sounds/emailup.mp3
Como explicado acima, o arquivo
template.SERVIDOREMAIL.UP.call se tornará o arquivo
1112103026.SERVIDOREMAIL.UP.call (supondo que o script tenha sido executado no dia 11 de dezembro, as 10 horas, 30 minutos e 26 segundos), que terá o seguinte conteúdo:
Channel:DAHDI/g1/NUMERODOCELULARDORESPONSÁVEL
Application: MP3Player
Data: /var/lib/asterisk/sounds/emailup.mp3
Em seguida, este arquivo será copiado via SCP para o servidor Asterisk, na pasta
/var/spool/asterisk/outgoing, e será executado gerando uma ligação para o número do celular do responsável e executando o arquivo de áudio
emailup.mp3.
Todos devem compreender, obviamente, o trabalho braçal enorme que se constituiu criar um arquivo
template.NOMEDOHOSTNONAGIOS.UP.call, e um arquivo
template.NOMEDOHOSTNONAGIOS.DOWN.call, e em seguida, criar um arquivo de áudio MP3 que falasse o nome do host e se ele se encontrava Down ou Up, correspondendo a cada um dos arquivos ".call". Mas o resultado valeu a pena. :).
Existem ainda outras possibilidades, como inserir o contexto no qual o arquivo será executado no Asterisk, e criar esse contexto, para que se possam fazer mais operações, ou enviar o responsável para uma URA, fazendo com que seja possível, por exemplo, que ele faça o Asterisk ligar para uma terceira pessoa ou algo assim... Enfim, quando falamos de Asterisk, o limite é nossa própria imaginação.
Temo que o presente artigo possa ter ficado um tanto confuso, mas foi a maneira que encontrei de compartilhar com a comunidade esta solução e, como não havia encontrado nada parecido Internet afora, achei que valia a pena postar.
Críticas, desde que construtivas e sugestões, são bem-vindas.