Havia a necessidade de monitorar o zoológico da UPS, Ippon, Powercom e Krauler estavam disponíveis. Como uma ferramenta de monitoramento usado Zabbix.Naturalmente, o problema precisava ser resolvido 1) mais barato 2) ainda mais barato, portanto a opção com módulos SNMP foi rejeitada imediatamente. Decidiu-se usar a conexão da porta serial, pois havia experiência em desenvolvimento para Ippon e APC. A propósito, a APC no mercado secundário possui módulos SNMP a um preço razoável, mas para no-breaks baratos, eu só consegui encontrar novos módulos a um preço de 11 a 20 mil rublos.No decorrer do trabalho, as seguintes tarefas adicionais foram definidas:- encontre e verifique os cabos para conectar cada no-break, porque não havia nenhum no kit
- Implemente um módulo que tenha uma interface RS-232, por um lado, e entenda o protocolo de troca de dados com cada no-break e, por outro, tenha uma interface de rede e possa enviar dados na forma de zabbix_trapper.
- Teste o modelo de coleta e transmissão de dados, partes do código e o formato dos dados.
Durante a implementação do segundo e terceiro parágrafo, eu queria coletar em um só lugar todos os dados que permitiriam no futuro implementar um dispositivo separado para m / c.Então:Não havia cabos para nenhum no-break. Em princípio, a primeira tarefa não apresenta um problema para as pessoas que podem contar contatos no conector DB9. Como se viu, nem todos sabem como, inclusive eu. Os contatos nos conectores F e M são espelhados, mas assinados, em geral, é impossível cometer um erro, se você for cuidadoso.- Ippon Smart Winner 2000 back power pro, 2-2, 3-3, 5-5. , .
- Krauler Memo RT 2000 krauler.ru, 2-2,3-3, 5-5.
- Powercom SXL-2000A www.pcm.ru/data/docs/cables.zip, forum.pcm.ru. 2-9, 3-6, 5-7. (-).
Um pequeno offtopic. A espinha dorsal do servidor é composta por dois hosts Vmware ESXi, alojados em um rack com dois no-breaks. Alguns servidores possuem 2 fontes de alimentação. E parte, infelizmente, é apenas uma, e é por isso que elas sofrem periodicamente. O Zabbix está atualmente hospedado em um dos hosts como uma máquina virtual. Em princípio, implantar um pequeno servidor virtual no Ubuntu (eu uso essa plataforma para serviços) para implementar qualquer tarefa não é um problema.Assim, o esquema desenvolveu: porta COM no ESXi -> porta Com na máquina virtual -> programa C que retorna dados do no-break -> script ou programa que envia armadilha zabbix. Os dois últimos pontos devem ser combinados no futuro. Embora funcione assim.O problema foi resolvido sequencialmente, conectando o cabo de um no-break, conectando um conector adicional ao servidor (existem dois deles, mais um adaptador rj-45 no DB9), verificando a conexão, verificando o programa, configurando os elementos no Zabbiks.- 2. Interrogação da porta COM pelo programa
A primeira coisa necessária foi escolher um servidor para hospedar o código executável. Eu não montei meu cérebro e postei tudo isso em um servidor Zabbix.Segundo, pensei em como processar os dados. Devido ao design no Basharray=( $(/home/appliance/uniups) )
que divide a string em uma matriz de dados, decidi apenas retornar o segmento de linha MMM.M NNN.N PPP.P QQQ RR.R S.SS TT.TCódigo do programa#include <stdio.h> /* / */
#include <string>
#include <iostream>
#include <cstring>
using namespace std;
#include <unistd.h> /* UNIX */
#include <fcntl.h> /* */
#include <errno.h> /* */
#include <termios.h> /* POSIX- */
#include <sys/types.h>
#include <sys/stat.h>
int fd;
char buf[512];
int main (int argc, char* argv[])
{
int iIn,iOut;
string UPSAnswer;
if (argc>=2)
{
fd = open(argv[1], O_RDWR | O_NOCTTY | O_NDELAY);
if (fd == -1) {
printf("error port\n");
perror("open_port: Unable to open port - "); }
else
{
struct termios options;
tcgetattr(fd, &options);
cfsetispeed(&options, B2400);
cfsetospeed(&options, B2400);
options.c_cflag &= ~PARENB;
options.c_cflag &= ~CSTOPB;
options.c_cflag &= ~CSIZE;
options.c_cflag |= CS8;
tcsetattr(fd, TCSANOW, &options);
}
char Params[64];
if(argc>=3)
{
if (!strcmp(argv[2],"status"))
{
iOut = write(fd, "Q1\r", 3);
usleep(800000);
if (iOut < 0) fputs("write() of 4 bytes failed!\n", stderr);
iIn=read(fd,buf,250);
strncpy(Params,&buf[38],11);
Params[46]=0;
}
else if (!strcmp(argv[2],"help"))
{
printf (" . !\r\n");
}
else if (!strcmp(argv[2],"name"))
{
iOut = write(fd, "I\r", 3);
usleep(800000);
if (iOut < 0) fputs("write() of 4 bytes failed!\n", stderr);
iIn=read(fd,buf,250);
strncpy(Params,&buf[0],60);
}
else if (!strcmp(argv[2],"stat2"))
{
iOut = write(fd, "F\r", 3);
usleep(800000);
if (iOut < 0) fputs("write() of 4 bytes failed!\n", stderr);
iIn=read(fd,buf,250);
strncpy(Params,&buf[1],60);
Params[20]=0;
}
else
{
printf ("? \r\n");
}
}
else
{
usleep(1800);
iIn=read(fd,buf,250);
usleep(1800);
iOut = write(fd, "Q1\r", 3);
usleep(800000);
if (iOut < 0) fputs("write() of 4 bytes failed!\n", stderr);
iIn=read(fd,buf,250);
strncpy(Params,&buf[1],36);
Params[36]=' ';
}
close(fd);
printf("%s\r\n",Params);
}
else
printf("Usage %s /dev/ttySx", argv[0]);
}
Encontrei trabalho com a porta no Google, você pode ler no Bash, mas no Bash não foi possível obter uma operação estável. Em princípio, o código C no linux é b. O primeiro Ippon foi testado; em seguida, durante o estudo do Powercom UPS, foi lançado um monitor de porta, o qual mostrou que o PowerCom também funciona via protocolo Megatec, e o programa nativo consulta o no-break na inicialização com os comandos "I" e "F" e depois ciclicamente "Q1". Pendurei o nome da porta na forma de "/ dev / ttyS0" ou "/ dev / ttyS1" no primeiro argumento, o segundo argumento permite que você solicite parâmetros adicionais, o código mostra.No diretório / home / appliance / colocou o programa, chamado uniups.cpp. Compiladog++ -o uniups uniups.cpp
.Em princípio, o resultado é algo assim (sim, eu trabalho sob a raiz, nem mesmo comento)root@zabbix:~
204.4 204.4 204.4 035 49.9 54.8 54.5
root@zabbix:~
I
root@zabbix:~
root@zabbix:~
216.3 216.3 216.3 000 50.0 54.2 30.0
root@zabbix:~
220.0 009 048.0 50.0
root@zabbix:~
O importante é que, no final, todos os no-breaks usam o mesmo protocolo, o que permitiu o uso de um programa. A conexão em 2400, 8N1 é usada, todo o resto está desativado. Houve uma mosca na pomada, o nome do no-break normalmente retorna apenas à Powercom, o Ippon não entende o comando "I" e o Krauler retorna "# R1.1.1".Além disso, o Krauler retorna a voltagem para o elemento e o restante do no-break para as baterias, na documentação descrita comoSS.S ou S.SS Para unidades on-line, a tensão / célula da bateria é fornecida no formato S.SS. Para unidades em espera, a tensão real da bateria é fornecida no formato SS.S
Em vista disso, eu tive que colocar um patch no script. Sobre isso abaixo.- 3. Enviando dados para o Zabbix
Com o envio, acabou um zoológico para todas as ocasiões. No servidor, o Zabbix usou o utilitário zabbix_sender para acelerar o processo.zabbix_sender -z _ -p 10051 -s ___ -k -o
Em princípio, para pesquisar dois no-breaks, basta que, neste momento, eu tenha um terceiro e, no futuro, um quarto. Por isso, selecionei o primeiro e, por uma estranha coincidência, o único servidor Linux no segundo host Vmware e o enviei para ele portas COM.Não usei o agente zabbix nem copiei o zabbix_sender. Encontrei a descrição deste último noAll salt consiste em codificar dados no Base64. Para verificar, usei o comandoecho "<req>\n<host>S3JhdWxlck1lbW9SVDIwMDA=</host>\n<key>RnJlcQ==</key>\n<data>NDkuNA==</data>\n</req>\n" | nc -q 0 192.168.53.23 10051
onde 192.168.53.23 é o endereço do servidor Zabbix. Ela está trabalhandoEu chamei o script acima zabbix_sender.pl e o coloquei no servidor, meu script fica assim:
use IO::Socket;
use IO::Select;
use MIME::Base64;
my ($zabbixserver,$hostname,$item,$data) = @_;
$zabbixserver= @ARGV[0];
$hostname= @ARGV[1];
$item= @ARGV[2];
$data= @ARGV[3];
my $timeout=10;
my $request=sprintf("<req>\n<host>%s</host>\n<key>%s</key>\n<data>%s</data>\n</req>\n",
encode_base64($hostname),encode_base64($item),encode_base64($data));
my $sock = new IO::Socket::INET ( PeerAddr => $zabbixserver, PeerPort => '10051', Proto => 'tcp', Timeout => $timeout);
die "Could not create socket: $!\n" unless $sock;
$sock->send($request);
my @handles=IO::Select->new($sock)->can_read($timeout);
if (scalar(@handles) > 0)
{
$sock->recv($result,1024);
print "answer from zabbix server $zabbixserver: $result\n";
}
else
{
print "no answer from zabbix server\n";
}
$sock->close();
Perl já estava no servidor.Em seguida, precisávamos de um script que vinculasse todos os componentes e que pudesse ser colocado no Cron.Aqui está um exemplo de uma porta; para outra porta, você pode simplesmente copiar o mesmo código e substituir um nome diferente. Eu não fiz o ciclo, mal imagino um carro com mais de 2 portas COM.#!/bin/bash
array=( $(//uniups /dev/ttyS0) )
Names=( InVolt FaultVolt OutVolt Current Freq UBatt UTemp NA )
correct[5]="24.0"
j=0;
echo "Checking UPS on serial A - ${#array[@]}"
if [ ${#array[@]} -gt "7" ]
then
param=""
for i in "${array[@]}"
do
if [[ ${correct[$j]} ]]
then
param=$( echo "scale = 0; $i * ${correct[$j]}" | bc)
else.
param=$i
fi
//zabbix_sender.pl 192.168.53.23 KraulerMemoRT2000 ${Names[$j]} $param
j=$j+1;
done
else
echo "No data on A"
fi
Pequenos comentários:- array - o array que o programa de pesquisa da UPS retorna, Names - um array com os nomes Item, nos elementos do servidor Zabbix com os mesmos nomes, deve ser iniciado. KraulerMemoRT2000 - o nome do ininterrupto, deve corresponder ao nome do host no servidor.
- , , Zabbix , , , NA, , , .
- ${#array[@]}, . , . : , , . , , . , , .
- correto [5] = "24.0" é a correção de tensão para as baterias (o quinto elemento do array) se o no-break retornar a tensão no elemento (tensão / célula da bateria). Eu tenho 6 elementos na bateria, 4 peças em série, totalizando 24. Em princípio, isso está descrito no protocolo. Achei desnecessário criar um elemento separado, pois todos os no-breaks que tenho são monitorados pelo modelo e todos têm 48 volts. Ao monitorar UPSs de tensões diferentes, é claro, será necessário alterar ligeiramente a estrutura; pode ser ideal martelar os parâmetros da bateria no servidor.
O script acima é adicionado ao cron para cada execução de minuto. A configuração do Zabbix não é considerada neste artigo.Em princípio, é tudo. Ficaria feliz se as informações coletadas forem úteis para alguém.