Este é um fork de um projeto do GIT com algumas correções. Verifique possíveis atualizações: https://github.com/germanodlf/bacula-zabbix
Esse projeto consiste de um shell script que coleta informações do servidor do Bacula, envia para o servidor Zabbix através de seu cliente (Zabbix sender), e um template a ser instalado no servidor de monitoração.
Características
- Monitoramento individual para cada Job de backup
- Diferentes níveis de Job têm diferentes gravidades
- Monitoramento dos processos do Diretor, Storage e Cliente do Bacula
- Gráficos e dashboards
- Funciona com Catálogos do Bacula em PostgreSQL e MySQL
Dados Coletados pelo Script
- Status de término do Job (item OK)
- Número de bytes transferidos (item Bytes)
- Número de arquivos transferidos (item Files)
- Duração (item Time)
- Taxa de transferência (item Speed)
- Taxa de compactação (item Compression)
Dados dos Processos do Bacula
- Status do processo do Bacula Director. O nome do processo é definido pela variável {$BACULA.DIR} e tem seu valor padrão como ‘bacula-dir’. Este item precisa ser desabilitado em hosts que são apenas clientes do Bacula.
- Status do Storage Daemon. O nome do processo é definido pela variável {$BACULA.SD} e tem seu valor padrão como ‘bacula-sd’. Este item precisa ser desabilitado em hosts que são apenas clientes do Bacula.
- Status do File Daemon. O nome do processo é definido pela variável {$ BACULA.FD} e tem seu valor padrão como ‘bacula-fd’.
Gatilhos
- O daemon do Bacula está DOWN em {HOST.NAME}: Inicia um alerta de gravidade do desastre quando o processo do Bacula está parado
- Backup Full FAIL em {HOST.NAME}: inicia um alerta de alta gravidade quando uma tarefa de backup completo falha
- Backup Diferencial FAIL em {HOST.NAME}: inicia um alerta de gravidade médio quando uma tarefa de backup diferencial falha
- Backup Incremental FAIL em {HOST.NAME}: inicia um alerta de gravidade de aviso quando uma tarefa de backup incremental falha
Configuração
Template Zabbix
Faça o download do template xml (zip) e importe-o para o seu servidor Zabbix.
Prossiga com a instalação do script nas máquinas com Bacula à seguir. Posteriormente, o modelo do Zabbix deverá ser fornecido a cada um desses hosts. Cada host configurado no Zabbix com este modelo vinculado precisa ter seu nome igual ao nome configurado no recurso Cliente do Bacula. Caso contrário, os dados coletados pelo script bash não serão recebidos pelo servidor Zabbix.
Script Zabbix Servidor Bacula
Instale o Zabbix Sender e o Agent. Exemplo CentOS 7:
rpm -Uivh https://repo.zabbix.com/zabbix/3.0/rhel/7/x86_64/zabbix-sender-3.0.22-1.el7.x86_64.rpm rpm -Uivh https://repo.zabbix.com/zabbix/3.0/rhel/7/x86_64/zabbix-agent-3.0.22-1.el7.x86_64.rpm systemctl enable zabbix-agent
Modifique as configurações do Agente Zabbix necessárias como endereço do Server, Porta e Hostname da máquina do agente, se necessário. Reinicie o serviço para aplicar as alterações:
vi /etc/zabbix/zabbix_agentd.conf ... Server=192.168.0.50 ListenPort=10051 ... :x! service zabbix-agent restart
Crie o arquivo de configuração /opt/bacula/etc/bacula-zabbix.conf com o seguinte conteúdo. Modifique com as informações de seu ambiente:
### BACULA CONFIG ### # IP address or FQDN of database server baculaDbAddr='127.0.0.1' # TCP port of database server baculaDbPort='5432' # Name of the database used by Bacula baculaDbName='bacula' # User used by Bacula on it's database baculaDbUser='bacula' # Password used by Bacula on it's database baculaDbPass='' ### ZABBIX CONFIG ### # IP address or FQDN of Zabbix server zabbixSrvAddr='192.168.37.200' # TCP port of Zabbix server zabbixSrvPort='10051' # Path to zabbix_sender command zabbixSender='/usr/bin/zabbix_sender'
Forneça permissões ao usuário Bacula ao arquivo .conf criado.
chown root:bacula /opt/bacula/etc/bacula-zabbix.conf chmod 640 /opt/bacula/etc/bacula-zabbix.conf
Crie o arquivo de script bash /opt/bacula/scripts/bacula-zabbix.bash, com o conteúdo que segue. Para Catálogo PostgreSQL:
#!/bin/bash # # For PGSQL # Import configuration file source /opt/bacula/etc/bacula-zabbix.conf sql="/usr/bin/psql -qtAX -h$baculaDbAddr -p$baculaDbPort -U$baculaDbUser -d$baculaDbName -c" # With Password # sql="PGPASSWORD=$baculaDbPass /usr/bin/psql -qtAX -h$baculaDbAddr -p$baculaDbPort -U$baculaDbUser -d$baculaDbName -c" # Get Job ID from parameter baculaJobId="$1" if [ -z $baculaJobId ] ; then exit 3 ; fi # Test if zabbix_sender exists and execute permission is granted, if not, exit if [ ! -x $zabbixSender ] ; then exit 5 ; fi # Get Job type from database, then if it is a backup job, proceed, if not, exit baculaJobType=$($sql "select Type from Job where JobId=$baculaJobId;" 2>/dev/null) if [ "$baculaJobType" != "B" ] ; then exit 9 ; fi # Get Job level from database and classify it as Full, Differential, or Incremental baculaJobLevel=$($sql "select Level from Job where JobId=$baculaJobId;" 2>/dev/null) case $baculaJobLevel in 'F') level='full' ;; 'D') level='diff' ;; 'I') level='incr' ;; *) exit 11 ;; esac # Get Job exit status from database and classify it as OK, OK with warnings, or Fail baculaJobStatus=$($sql "select JobStatus from Job where JobId=$baculaJobId;" 2>/dev/null) if [ -z $baculaJobStatus ] ; then exit 13 ; fi case $baculaJobStatus in "T") status=0 ;; "W") status=1 ;; *) status=2 ;; esac # Get client's name from database baculaClientName=$($sql "select Client.Name from Client,Job where Job.ClientId=Client.ClientId and Job.JobId=$baculaJobId;" 2>/dev/null) if [ -z $baculaClientName ] ; then exit 15 ; fi # Initialize return as zero return=0 # Send Job exit status to Zabbix server $zabbixSender -z $zabbixSrvAddr -p $zabbixSrvPort -s $baculaClientName -k "bacula.$level.job.status" -o $status >/dev/null 2>&1 if [ $? -ne 0 ] ; then return=$(($return+1)) ; fi # Get from database the number of bytes transferred by the Job and send it to Zabbix server baculaJobBytes=$($sql "select JobBytes from Job where JobId=$baculaJobId;" 2>/dev/null) $zabbixSender -z $zabbixSrvAddr -p $zabbixSrvPort -s $baculaClientName -k "bacula.$level.job.bytes" -o $baculaJobBytes >/dev/null 2>&1 if [ $? -ne 0 ] ; then return=$(($return+2)) ; fi # Get from database the number of files transferred by the Job and send it to Zabbix server baculaJobFiles=$($sql "select JobFiles from Job where JobId=$baculaJobId;" 2>/dev/null) $zabbixSender -z $zabbixSrvAddr -p $zabbixSrvPort -s $baculaClientName -k "bacula.$level.job.files" -o $baculaJobFiles >/dev/null 2>&1 if [ $? -ne 0 ] ; then return=$(($return+4)) ; fi # Get from database the time spent by the Job and send it to Zabbix server baculaJobTime=$($sql "select round(cast( float8 (EXTRACT(EPOCH FROM EndTime-StartTime)) as numeric)) from Job where JobId=$baculaJobId;" 2>/dev/null) $zabbixSender -z $zabbixSrvAddr -p $zabbixSrvPort -s $baculaClientName -k "bacula.$level.job.time" -o $baculaJobTime >/dev/null 2>&1 if [ $? -ne 0 ] ; then return=$(($return+8)) ; fi # Get Job speed from database and send it to Zabbix server baculaJobSpeed=$($sql "select case when EXTRACT(EPOCH FROM EndTime-StartTime) <= 0 then 0 else round(cast( float8 (JobBytes/EXTRACT(EPOCH FROM EndTime-StartTime)/1024) as numeric),2) end from Job where JobId=$baculaJobId;" 2>/dev/null) $zabbixSender -z $zabbixSrvAddr -p $zabbixSrvPort -s $baculaClientName -k "bacula.$level.job.speed" -o $baculaJobSpeed >/dev/null 2>&1 if [ $? -ne 0 ] ; then return=$(($return+16)) ; fi # Get Job compression rate from database and send it to Zabbix server baculaJobCompr=$($sql "select round(1-JobBytes/ReadBytes,2) from Job where JobId=$baculaJobId;" 2>/dev/null) $zabbixSender -z $zabbixSrvAddr -p $zabbixSrvPort -s $baculaClientName -k "bacula.$level.job.compr" -o $baculaJobCompr >/dev/null 2>&1 if [ $? -ne 0 ] ; then return=$(($return+32)) ; fi # Exit with return status exit $return
Para Catálogo MySQL:
#!/bin/bash # # For MYSQL # Import configuration file source /opt/bacula/etc/bacula-zabbix.conf sql="/usr/bin/mysql -NB -h$baculaDbAddr -P$baculaDbPort -u$baculaDbUser -p$baculaDbPass -D$baculaDbName -e" # Get Job type from database, then if it is a backup job, proceed, if not, exit baculaJobType=$($sql "select Type from Job where JobId=$baculaJobId;" 2>/dev/null) if [ "$baculaJobType" != "B" ] ; then exit 9 ; fi # Get Job level from database and classify it as Full, Differential, or Incremental baculaJobLevel=$($sql "select Level from Job where JobId=$baculaJobId;" 2>/dev/null) case $baculaJobLevel in 'F') level='full' ;; 'D') level='diff' ;; 'I') level='incr' ;; *) exit 11 ;; esac # Get Job exit status from database and classify it as OK, OK with warnings, or Fail baculaJobStatus=$($sql "select JobStatus from Job where JobId=$baculaJobId;" 2>/dev/null) if [ -z $baculaJobStatus ] ; then exit 13 ; fi case $baculaJobStatus in "T") status=0 ;; "W") status=1 ;; *) status=2 ;; esac # Get client's name from database baculaClientName=$($sql "select Client.Name from Client,Job where Job.ClientId=Client.ClientId and Job.JobId=$baculaJobId;" 2>/dev/null) if [ -z $baculaClientName ] ; then exit 15 ; fi # Initialize return as zero return=0 # Send Job exit status to Zabbix server $zabbixSender -z $zabbixSrvAddr -p $zabbixSrvPort -s $baculaClientName -k "bacula.$level.job.status" -o $status >/dev/null 2>&1 if [ $? -ne 0 ] ; then return=$(($return+1)) ; fi # Get from database the number of bytes transferred by the Job and send it to Zabbix server baculaJobBytes=$($sql "select JobBytes from Job where JobId=$baculaJobId;" 2>/dev/null) $zabbixSender -z $zabbixSrvAddr -p $zabbixSrvPort -s $baculaClientName -k "bacula.$level.job.bytes" -o $baculaJobBytes >/dev/null 2>&1 if [ $? -ne 0 ] ; then return=$(($return+2)) ; fi # Get from database the number of files transferred by the Job and send it to Zabbix server baculaJobFiles=$($sql "select JobFiles from Job where JobId=$baculaJobId;" 2>/dev/null) $zabbixSender -z $zabbixSrvAddr -p $zabbixSrvPort -s $baculaClientName -k "bacula.$level.job.files" -o $baculaJobFiles >/dev/null 2>&1 if [ $? -ne 0 ] ; then return=$(($return+4)) ; fi # Get from database the time spent by the Job and send it to Zabbix server baculaJobTime=$($sql "select timestampdiff(second,StartTime,EndTime) from Job where JobId=$baculaJobId;" 2>/dev/null) $zabbixSender -z $zabbixSrvAddr -p $zabbixSrvPort -s $baculaClientName -k "bacula.$level.job.time" -o $baculaJobTime >/dev/null 2>&1 if [ $? -ne 0 ] ; then return=$(($return+8)) ; fi # Get Job speed from database and send it to Zabbix server baculaJobSpeed=$($sql "select round(JobBytes/timestampdiff(second,StartTime,EndTime)/1024,2) from Job where JobId=$baculaJobId;" 2>/dev/null) $zabbixSender -z $zabbixSrvAddr -p $zabbixSrvPort -s $baculaClientName -k "bacula.$level.job.speed" -o $baculaJobSpeed >/dev/null 2>&1 if [ $? -ne 0 ] ; then return=$(($return+16)) ; fi # Get Job compression rate from database and send it to Zabbix server baculaJobCompr=$($sql "select round(1-JobBytes/ReadBytes,2) from Job where JobId=$baculaJobId;" 2>/dev/null) $zabbixSender -z $zabbixSrvAddr -p $zabbixSrvPort -s $baculaClientName -k "bacula.$level.job.compr" -o $baculaJobCompr >/dev/null 2>&1 if [ $? -ne 0 ] ; then return=$(($return+32)) ; fi # Exit with return status exit $return
Reinicie o serviço do Director.
service bacula-dir restart
Monitoração dos Clientes Bacula
Edite seus hosts que configuraram tarefas de backup para usar o template do Zabbix. Não esqueça desabilitar nos hosts que são apenas clientes do Bacula os itens que checam os processos do Bacula Director e Storage, e de usar o nome do Host na console do Zabbix igual ao nome dos Clientes configurados no Bacula, como no exemplo (Client Name BKP01-fd):
Você pode executar o script manualmente inforomando um JobId para passar as informações (ex.: 99) para testar os scripts.
/opt/bacula/scripts/bacula-zabbix.bash 99
Em caso de problemas, você pode executar com a opção sh -x para depurar as consultas ao Catálogo do Bacula.
sh -x /opt/bacula/scripts/bacula-zabbix.bash 110 # Queries will appear. Try one. /usr/bin/zabbix_sender -z 192.168.0.50 -p 10051 -s BKP01-fd -k bacula.diff.job.speed -o 137.89 info from server: "processed: 1; failed: 0; total: 1; seconds spent: 0.000070" sent: 1; skipped: 0; total: 1
Adicione no JobDefs do Bacula uma configuração para sempre executar os clientes após todo Job de backup terminado, passando o JobId do mesmo:
RunAfterJob="/opt/bacula/scripts/bacula-zabbix.bash %i"
Screenshots
Disponível em: PortuguêsEnglish (Inglês)Español (Espanhol)
Boa tarde,
Estou tentando executar o procedimento no bacula 9.0.9, porem tenho essa saída:
[root@prod-bacula scripts]# sh -x /etc/bacula/scripts/bacula-zabbix.bash 669
+ source /etc/bacula/bacula-zabbix.conf
++ baculaDbSgdb=M
++ baculaDbAddr=intranet.aaaaaaaaaaaaaaaa.amazonaws.com
++ baculaDbPort=xxxx
++ baculaDbName=xxxx
++ baculaDbUser=bacula
++ baculaDbPass=’aaaaaaaaaaaaaaaaaaa’
++ zabbixSrvAddr=noc
++ zabbixSrvPort=10051
++ zabbixSender=/bin/zabbix_sender
+ sql=’/usr/bin/mysql -hintranet.aaaaaaaaaaaaaaaa.amazonaws.com -uxxxx -paaaaaaaaaaaaaaaaaaa -Dbacula -e’
+ baculaJobId=669
+ ‘[‘ -z 669 ‘]’
++ /usr/bin/mysql -hintranet.aaaaaaaaaaaaaaaa.amazonaws.com -uxxxx ‘-paaaaaaaaaaaaaaaaaaa’ -Dbacula -e ‘select Type from Job where JobId=669;’
+ baculaJobType=’Type
B’
+ ‘[‘ ‘Type
B’ ‘!=’ B ‘]’
+ exit 9
Olá. Teste no Shell ou no console SQL a consulta que termina em erro.