كانت هناك حاجة لرصد حديقة حيوان UPS ، Ippon ، Powercom و Krauler. كأداة رصد تستخدم Zabbix.بطبيعة الحال ، يجب حل المشكلة 1) بثمن بخس 2) أرخص ، لذلك تم رفض الخيار مع وحدات SNMP على الفور. تقرر استخدام اتصال المنفذ التسلسلي ، نظرًا لوجود تجربة تطوير لـ Ippon و APC. بالمناسبة ، يحتوي APC في السوق الثانوية على وحدات SNMP بسعر معقول ، ولكن بالنسبة لأجهزة UPS غير المكلفة ، لم أتمكن من العثور إلا على وحدات جديدة بسعر 11-20 ألف روبل.في سياق العمل ، تم تحديد المهام الإضافية التالية:- ابحث عن الكابلات وافحصها لتوصيل كل UPS ، لعدم وجود أي منها في المجموعة
- لتنفيذ وحدة معينة من شأنها أن تحتوي على واجهة RS-232 من ناحية وفهم بروتوكول تبادل البيانات مع كل UPS ، ومن ناحية أخرى ، لديها واجهة شبكة ويمكن أن ترسل البيانات في شكل zabbix_trapper.
- اختبار نموذج جمع البيانات ونقلها ، وأجزاء من الرمز ، وكذلك تنسيق البيانات.
أثناء تنفيذ الفقرتين الثانية والثالثة ، أردت أن أجمع في مكان واحد جميع البيانات التي ستسمح في المستقبل بتنفيذ جهاز منفصل لـ m / c.لذا:لم يكن هناك أي كابلات لأي UPS. من حيث المبدأ ، لا تمثل المهمة الأولى مشكلة للأشخاص الذين يمكنهم حساب جهات الاتصال على موصل DB9. كما اتضح ، ليس الجميع فقط يعرفون كيف ، بما في ذلك أنا. يتم عكس جهات الاتصال على موصلات F و M ، ولكن يتم توقيعها بشكل عام ، من المستحيل ارتكاب خطأ ، إذا كنت حذراً.- 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. (-).
offtopic صغير. يتكون العمود الفقري للخادم من مضيفين Vmware ESXi ، وهما موجودان في رف مع اثنين من UPS. تحتوي بعض الخوادم على إثنين من مصادر الطاقة. وجزء ، للأسف ، هو واحد فقط ، ولهذا السبب يعانون بشكل دوري. تتم استضافة Zabbix حاليًا على أحد الأجهزة المضيفة كآلة افتراضية. من حيث المبدأ ، فإن نشر خادم افتراضي صغير على Ubuntu (أستخدم هذا النظام الأساسي للخدمات) لتنفيذ أي مهمة لا يمثل مشكلة.وبالتالي ، كان المخطط على النحو التالي: منفذ COM على ESXi -> منفذ Com على الجهاز الظاهري -> برنامج C الذي يعيد البيانات من UPS -> Script أو البرنامج الذي يرسل فخ zabbix. يجب الجمع بين النقطتين الأخيرتين في المستقبل. على الرغم من أنه يعمل بهذه الطريقة.تم حل المشكلة بالتسلسل ، عن طريق توصيل الكبل لجهاز UPS واحد ، عن طريق توصيل موصل إضافي للخادم (هناك اثنان ، بالإضافة إلى محول rj-45 في DB9) ، والتحقق من الاتصال ، والتحقق من البرنامج ، وإعداد العناصر في Zabbix.- 2. استجواب منفذ COM بواسطة البرنامج
أول شيء كان مطلوبًا هو اختيار خادم لاستضافة التعليمات البرمجية القابلة للتنفيذ. لم أقم بتثبيت أدمغتي ونشرت كل هذا على خادم Zabbix.ثانيًا ، فكرت في كيفية معالجة البيانات. بسبب التصميم في باشarray=( $(/home/appliance/uniups) )
التي تقسم السلسلة إلى صفيف من البيانات ، قررت فقط إرجاع مقطع السطر MMM.M NNN.N PPP.P QQQ RR.R S.SS TT.Tكود البرنامج#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]);
}
لقد وجدت عملًا مع المنفذ في Google ، يمكنك القراءة من Bash ، ولكن من Bash لم يكن من الممكن تحقيق عملية مستقرة. من حيث المبدأ ، فإن رمز C في لينكس هو ب. تم اختبار أول Ippon ، ثم أثناء دراسة Powercom UPS ، تم إطلاق شاشة منفذ ، والتي أظهرت أن PowerCom تعمل أيضًا عبر بروتوكول Megatec ، ويقوم البرنامج الأصلي باستطلاع UPS عند بدء التشغيل باستخدام أمري "I" و "F" ، ثم دوريًا "Q1". قمت بتعليق اسم المنفذ في شكل "/ dev / ttyS0" أو "/ dev / ttyS1" في الوسيطة الأولى ، تسمح لك الوسيطة الثانية بطلب معلمات إضافية ، يظهر الرمز.في الدليل / المنزل / الجهاز / وضع البرنامج ، أطلق عليه uniups.cpp. جمعتg++ -o uniups uniups.cpp
.من حيث المبدأ ، النتيجة هي شيء من هذا القبيل (نعم ، أعمل تحت الجذر ، لا تعلق حتى)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:~
ما هو مهم ، في النهاية اتضح أن جميع UPS تستخدم نفس البروتوكول ، الذي سمح باستخدام برنامج واحد. يتم استخدام الاتصال على 2400 ، 8N1 ، كل شيء آخر مغلق. كان هناك ذبابة في المرهم ، وعادة ما يعود اسم UPS فقط إلى Powercom ، ولا يفهم Ippon الأمر "I" ، ويعيد Krauler "# R1.1.1".بالإضافة إلى ذلك ، ترجع Krauler الجهد إلى العنصر ، وبقية UPS إلى البطاريات ، في الوثائق التي توصف بأنهاSS.S أو S.SS للوحدات على الخط ، يتم توفير جهد / خلية البطارية على شكل S.SS. بالنسبة للوحدات الاحتياطية ، يتم توفير جهد البطارية الفعلي في شكل SS.S
في ضوء ذلك ، كان علي أن أضع التصحيح على البرنامج النصي. حول ذلك أدناه.- 3. إرسال البيانات إلى Zabbix
مع إرسال هذا تبين حديقة الحيوان لجميع المناسبات. على الخادم ، استخدمت Zabbix الأداة المساعدة zabbix_sender لتسريع العملية.zabbix_sender -z _ -p 10051 -s ___ -k -o
من حيث المبدأ ، بالنسبة لاستطلاع اثنين من UPS ، هذا يكفي ، ولكن في هذه اللحظة ، سيكون لدي ثالث ، وفي المستقبل سيكون لدي الرابع ، لذلك اخترت أول واحد ، وبمصادفة غريبة ، خادم Linux الوحيد على مضيف Vmware الثاني وطرحه إلى له منافذ COM.لم أستخدم عامل zabbix أو نسخ zabbix_sender ، لقد وجدت أن وصف الأخير علىAll salt يتكون من ترميز البيانات في Base64. للتحقق ، استخدمت الأمرecho "<req>\n<host>S3JhdWxlck1lbW9SVDIwMDA=</host>\n<key>RnJlcQ==</key>\n<data>NDkuNA==</data>\n</req>\n" | nc -q 0 192.168.53.23 10051
حيث 192.168.53.23 هو عنوان خادم Zabbix. إنها تعمل.دعوت النص البرمجي أعلاه zabbix_sender.pl ووضعته على الخادم ، يبدو النص البرمجي كما يلي:
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 بالفعل على الخادم.بعد ذلك ، كنا بحاجة إلى برنامج نصي يربط جميع المكونات معًا ويمكن وضعه في Cron.هنا مثال لمنفذ واحد ، لمنفذ آخر يمكنك ببساطة نسخ نفس الرمز واستبدال اسم مختلف. لم أقم بالدورة ، بالكاد أتخيل سيارة بها أكثر من منفذي 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
تعليقات صغيرة:- المصفوفة - المصفوفة التي يُرجعها برنامج الاستقصاء UPS ، الأسماء - يجب بدء مصفوفة بأسماء العنصر ، على عناصر خادم Zabbix بنفس الأسماء. KraulerMemoRT2000 - يجب أن يتطابق اسم غير المنقطع مع اسم المضيف على الخادم.
- , , Zabbix , , , NA, , , .
- ${#array[@]}, . , . : , , . , , . , , .
- الصحيح [5] = "24.0" هو تصحيح الجهد للبطاريات (العنصر الخامس في المصفوفة) إذا قامت UPS بإرجاع الجهد على العنصر (جهد / خلية البطارية). لدي 6 عناصر في البطارية ، 4 قطع في السلسلة ، إجمالي 24. من حيث المبدأ ، يتم وصف هذا في البروتوكول. لقد وجدت أنه من غير الضروري إنشاء عنصر منفصل ، نظرًا لأن جميع وحدات UPS التي قمت بمراقبتها بواسطة القالب ولديها 48 فولت. عند مراقبة UPS من الفولتية المختلفة ، بالطبع ، سيكون من الضروري تغيير الهيكل قليلاً ، قد يكون من الأفضل وضع معلمات البطارية على الخادم.
يضاف النص أعلاه إلى كرون لكل دقيقة تنفيذ. لا يعتبر إعداد Zabbix في هذه المقالة.من حيث المبدأ ، هذا كل شيء. سأكون سعيدًا إذا كانت المعلومات التي تم جمعها مفيدة لشخص ما.