Сейчас будем разбираться с оповещениями zabbix на jabber. В ранних статьях мы уже устанавливали jabber сервер Openfire и будем использовать его на примере.
Для начала, в opebfire необходимо создать пользователя для zabbix сервера с которого будем отправлять сообщения и добавляем его в группу.
С коробки zabbix я не смог отправлять оповещения, поэтому будем использовать скрипт.
создаем файл jabber в /etc/zabbix/alert.d:
nano /etc/zabbix/alert.d/jabber
#!/usr/bin/perl use common::sense; use Net::XMPP; use constant { SERVER => 'jabber.domain.ru', PORT => 5222, USER => 'server', PASSWORD => 'password', RESOURCE => 'company', TLS => 0, DEBUG => 0, }; $0 =~ s{.*/}{}; my ($to, $subj, $body, $type) = @ARGV; $type ||= 'headline'; die << "EOF" unless @ARGV == 3 or @ARGV == 4; Usage: $0[type] EOF utf8::decode($subj); utf8::decode($body); my $bot = new Net::XMPP::Client( debuglevel => DEBUG ); $bot->SetCallBacks( onconnect => sub{}, onauth => sub{ $bot->PresenceSend; $bot->MessageSend( to => $to, subject => $subj, body => $body, type => $type ); $bot->Disconnect(); }, ondisconnect => sub{} ); $bot->Execute( hostname => SERVER, port => PORT, tls => TLS, username => USER, password => PASSWORD, resource => RESOURCE, register => 0, connectiontype => 'tcpip' );
Делаем его запускающимся:
chmod +x /etc/zabbix/alert.d/jabber
cd /etc/zabbix/alert.d
Пробуем запустить:
./jabber
Получаем вот такую ошибку, а все из-за того что скрипт использует модули perl common::sense; Net::XMPP;
Can’t locate common/sense.pm in @INC (@INC contains: /etc/perl /usr/local/lib/perl/5.10.1 /usr/local/share/perl/5.10.1 /usr/lib/perl5 /usr/share/perl5 /usr/lib/perl/5.10 /usr/share/perl/5.10 /usr/local/lib/site_perl .) at ./jabber line 3.
BEGIN failed—compilation aborted at ./jabber line 3.
perl -MCPAN -e 'install +common::sense'
perl -MCPAN -e 'install +Net::XMPP'
Пробуем отправить сообщение с помощью скрипта:
./jabber [email protected] test test
сообщения также не доходят (тишина).
Добавлено из комментарий (спасибо Андрею):
Необходимо найти и закомментировать строку в
/usr/local/share/perl/5.14.2/Net/XMPP/Protocol.pm
return $self->AuthSASL(%args);
Кстати, в скрипте можно включить debug для просмотра где у нас ошибка:
DEBUG => 1,
Так же смотрим логи openfire в /var/log/openfire/warn.log
Важный момент:
Если у вас Openfire заведен на поддомене, например jabber.domain.ru, то и отправлять сообщения пользователю нужно с указанием с доменом третьего уровня:
./jabber [email protected] test test
Теперь остается в Вебморде zabbix добавить скрипт:
Администрирование -> Типы средств передачи -> Jabber — где Тип: выбрать Сценарий, Название скрипта — jabber
после запуска скрипта не приходит сообщение в дэбаге постоянно пишет
XMPP::Conn: SendAndReceiveWithID: sent with id(netjabber-0)
XMPP::Conn: WaitForID: id(netjabber-0)
XMPP::Conn: ReceivedID: id(netjabber-0)
XMPP::Conn: ReceivedID: nope…
XMPP::Conn: WaitForID: haven’t gotten it yet… let’s wait for more packets
XMPP::Conn: Process: timeout(1)
Еще добавлю. На голой системе нет модулей perl common::sense; Net::XMP.
Порядок установки:
sudo apt-get install perl build-essential libssl-dev
sudo perl -MCPAN -e ‘install O::Socket::SSL’
sudo perl -MCPAN -e ‘install Net::SSLeay’
sudo perl -MCPAN -e ‘install common::sense’
sudo perl -MCPAN -e ‘install Net::XMPP’
Использую готовое решние Zabbix 3.0, возникла проблема при подключении модулей, т.е. они просто ни в какую не ставятся, хотя на обычной машине все норм
Zabbix 3.0.0alpha5
Скрипт устанавливается нормально
Тестовый запуск /usr/local/share/zabbix/alertscripts/jabber u[email protected] test test срабатывает нормально, сообщение приходит
Zabbix пишет что отправил сообщение
Но я сообщений не вижу в jabber-клиенте (spark)
Такая же история. Решение нашлось?
Нашлось. При добавлении «способа оповещений» в zabbix указываем 3 параметра запуска отдельно
А можно подробнее? Что значит отдельно?
Разобрался. Начиная с 3.0 версии в параметрах нужно использовать макросы {ALERT.SENDTO}, {ALERT.SUBJECT} {ALERT.MESSAGE}, вместо старых $1 $2 $3.
Заработало!
А как из скрипта отправить сообщение в конференцию?
Если просто указать в качестве получателя адрес конференции — не канает.
Если использовать готовый дистр zabbix на базе SuSE, то в нем отсутствует make и perl -MCPAN -e ‘install +common::sense’ не завершится.
Выполняем yast -i make и продолжаем…
Если у кого была такая же проблема, то все решается просто: сообщению по-умолчанию делается тип «chat» и еще нужна задержка между выполнением команд. Вот мой код:
#!/usr/bin/perl
use common::sense;
use Net::XMPP;
use constant {
SERVER => ‘server’,
PORT => 5222,
USER => ‘zabbix’,
PASSWORD => ‘pass’,
RESOURCE => ‘script’,
TLS => 0,
DEBUG => 1,
};
my $lock_file = ‘./.lock’;
# Ждем отсутствия файла lock
while (-f $lock_file)
{
sleep(10);
}
#Создаем lock файл
open(FILE, «> $lock_file»);
close(FILE);
$0 =~ s{.*/}{};
my ($to, $subj, $body, $type) = @ARGV;
$type ||= ‘chat’;
#Если косяк в аргументах lock все равно удаляем
unless (@ARGV == 3 or @ARGV == 4)
{
unlink $lock_file;
}
die << "EOF" unless @ARGV == 3 or @ARGV == 4;
Usage: $0 [type]
EOF
utf8::decode($subj);
utf8::decode($body);
my $bot = new Net::XMPP::Client( debuglevel => DEBUG, debugfile =>»/usr/local/share/zabbix/alertscripts/jabber_log.log»);
$bot->SetCallBacks(
onconnect => sub{},
onauth => sub{
$bot->PresenceSend;
$bot->MessageSend( to => $to, subject => $subj, body => $body, type => $type );
$bot->Disconnect();
},
ondisconnect => sub{}
);
$bot->Execute(
hostname => SERVER,
port => PORT,
tls => TLS,
username => USER,
password => PASSWORD,
resource => RESOURCE,
register => 0,
connectiontype => ‘tcpip’
);
sleep(10);
#Удаляем lock файл
unlink $lock_file;
Спасибо! Очень полезная статья. Но у меня возникла проблема со скриптом. При отправке сообщений из zabbix’a на 4 разичных аккаунта сообщения доходили не всем. В процессе тестирования обнаружилось, что если отправлять из командной строки друг за другом сообщения, часть из них не доходит. Также не доходят сообщения если клиент оффлайн… Может, кто-нибудь сталкивался с такой проблемой?
{{Hider|Лог отправки, если клиент оффлайн
XML::Stream: new: hostname = (openfire)
XML::Stream: SetCallBacks: tag(node) func(CODE(0x204ef18))
XMPP::Conn: xmppCallbackInit: start
XMPP::Conn: SetCallBacks: tag(message) func(CODE(0x2369850))
XMPP::Conn: SetCallBacks: tag(presence) func(CODE(0x2364fb8))
XMPP::Conn: SetCallBacks: tag(iq) func(CODE(0x2364e08))
XMPP::Conn: SetPresenceCallBacks: type(subscribe) func(CODE(0x2364fe8))
XMPP::Conn: SetPresenceCallBacks: type(subscribed) func(CODE(0x2369d90))
XMPP::Conn: SetPresenceCallBacks: type(unsubscribe) func(CODE(0x2369c10))
XMPP::Conn: SetPresenceCallBacks: type(unsubscribed) func(CODE(0x2369f10))
XMPP::Conn: SetDirectXPathCallBacks: xpath(/[@xmlns=»urn:ietf:params:xml:ns:xmpp-tls»]) func(CODE(0x2369dc0))
XMPP::Conn: SetDirectXPathCallBacks: xpath(/[@xmlns=»urn:ietf:params:xml:ns:xmpp-sasl»]) func(CODE(0x236a180))
XMPP::Conn: xmppCallbackInit: stop
XMPP::Conn: SetCallBacks: tag(ondisconnect) func(CODE(0x23a5f68))
XMPP::Conn: SetCallBacks: tag(onauth) func(CODE(0x236a780))
XMPP::Conn: SetCallBacks: tag(onconnect) func(CODE(0x2318740))
XMPP::Conn: Execute: begin
XMPP::Conn: Execute: Attempt to connect (-1)
XMPP::Conn: Connect: host(server:5222) namespace(jabber:client)
XMPP::Conn: Connect: timeout(10)
XML::Stream: Connect: type(tcpip)
XML::Stream: Connect: Got a connection
XML::Stream: Send: ()
XML::Stream: Read: buff(PLAINANONYMOUSzlib)
XMPP::Conn: Connect: connection made
XML::Stream: SetCallBacks: tag(node) func(CODE(0x2370258))
XMPP::Conn: Execute: Connected…
XMPP::Conn: AuthSASL: shiney new auth
XML::Stream: Send: (emFiYml4QGJhbmstcGVyZXN2ZXQucnUAemFiYml4ADEyMw==)
XMPP::Conn: AuthSASL: haven’t authed yet… let’s wait.
XMPP::Conn: Process: timeout(1)
XML::Stream: Read: buff()
XMPP::Conn: AuthSASL: We authed!
XML::Stream: Send: ()
XML::Stream: Read: buff(zlib)
XMPP::Conn: AuthSASL: We got a new session. sid(b74d0583)
XMPP::Conn: AuthSASL: Binding to resource
XMPP::Conn: SendAndReceiveWithID: object(Net::XMPP::IQ=HASH(0x23522d8))
XMPP::Conn: SendWithID: id(netjabber-0)
XMPP::Conn: SendWithID: in(script)
XMPP::Conn: RegisterID: tag(iq) id(netjabber-0)
XMPP::Conn: SendWithID: out(script)
XMPP::Conn: SendXML: sent(script)
XML::Stream: Send: (script)
XMPP::Conn: SendAndReceiveWithID: sent with id(netjabber-0)
XMPP::Conn: WaitForID: id(netjabber-0)
XMPP::Conn: ReceivedID: id(netjabber-0)
XMPP::Conn: ReceivedID: nope…
XMPP::Conn: WaitForID: haven’t gotten it yet… let’s wait for more packets
XMPP::Conn: Process: timeout(1)
XML::Stream: Read: buff([email protected]/script)
XMPP::Conn: CallBack: sid(b74d0583) received([email protected]/script)
XMPP::Conn: CallBack: tag(iq)
XMPP::Conn: CallBack: id(netjabber-0)
XMPP::Conn: CallBack: we either want it or were waiting for it.
XMPP::Conn: CallBack: check directxpath
XMPP::Conn: CallBack: check directxpath(/[@xmlns=»urn:ietf:params:xml:ns:xmpp-sasl»])
XMPP::Conn: CallBack: check directxpath(/[@xmlns=»urn:ietf:params:xml:ns:xmpp-tls»])
XMPP::Conn: BuildObject: tag(iq) package(Net::XMPP::IQ)
XMPP::Conn: CheckID: tag(iq) id(netjabber-0)
XMPP::Conn: CheckID: we have that here somewhere…
XMPP::Conn: CallBack: found registry entry: tag(iq) id(netjabber-0)
XMPP::Conn: DeregisterID: tag(iq) id(netjabber-0)
XMPP::Conn: CallBack: they still want it… we still got it…
XMPP::Conn: GotID: id(netjabber-0) xml([email protected]/script)
XMPP::Conn: ReceivedID: id(netjabber-0)
XMPP::Conn: ReceivedID: id(netjabber-0)
XMPP::Conn: WaitForID: we got it!
XMPP::Conn: GetID: id(netjabber-0)
XMPP::Conn: ReceivedID: id(netjabber-0)
XMPP::Conn: CleanID: id(netjabber-0)
XMPP::Conn: AuthSASL: Starting session
XMPP::Conn: SendAndReceiveWithID: object(Net::XMPP::IQ=HASH(0x1db2b20))
XMPP::Conn: SendWithID: id(netjabber-1)
XMPP::Conn: SendWithID: in()
XMPP::Conn: RegisterID: tag(iq) id(netjabber-1)
XMPP::Conn: SendWithID: out()
XMPP::Conn: SendXML: sent()
XML::Stream: Send: ()
XMPP::Conn: SendAndReceiveWithID: sent with id(netjabber-1)
XMPP::Conn: WaitForID: id(netjabber-1)
XMPP::Conn: ReceivedID: id(netjabber-1)
XMPP::Conn: ReceivedID: nope…
XMPP::Conn: WaitForID: haven’t gotten it yet… let’s wait for more packets
XMPP::Conn: Process: timeout(1)
XML::Stream: Read: buff()
XMPP::Conn: CallBack: sid(b74d0583) received()
XMPP::Conn: CallBack: tag(iq)
XMPP::Conn: CallBack: id(netjabber-1)
XMPP::Conn: CallBack: we either want it or were waiting for it.
XMPP::Conn: CallBack: check directxpath
XMPP::Conn: CallBack: check directxpath(/[@xmlns=»urn:ietf:params:xml:ns:xmpp-sasl»])
XMPP::Conn: CallBack: check directxpath(/[@xmlns=»urn:ietf:params:xml:ns:xmpp-tls»])
XMPP::Conn: BuildObject: tag(iq) package(Net::XMPP::IQ)
XMPP::Conn: CheckID: tag(iq) id(netjabber-1)
XMPP::Conn: CheckID: we have that here somewhere…
XMPP::Conn: CallBack: found registry entry: tag(iq) id(netjabber-1)
XMPP::Conn: DeregisterID: tag(iq) id(netjabber-1)
XMPP::Conn: CallBack: they still want it… we still got it…
XMPP::Conn: GotID: id(netjabber-1) xml()
XMPP::Conn: ReceivedID: id(netjabber-1)
XMPP::Conn: ReceivedID: id(netjabber-1)
XMPP::Conn: WaitForID: we got it!
XMPP::Conn: GetID: id(netjabber-1)
XMPP::Conn: ReceivedID: id(netjabber-1)
XMPP::Conn: CleanID: id(netjabber-1)
XMPP::Conn: SendXML: sent()
XML::Stream: Send: ()
XMPP::Conn: SendXML: sent(88123)
XML::Stream: Send: (88123)
XML::Stream: Send: ()
XML::Stream: SetCallBacks: tag(node) func(CODE(0x237b838))
XMPP::Conn: Disconnect: bye bye
XMPP::Conn: Connected: (0)
XMPP::Conn: Execute: end
}}
В сущности, он такой же, как и если клиент онлайн, но привожу на всякий случай…
извеняюсь что так долго не отвечал.. у меня заработало без скрипта.. на стороннем сервере где openfire установлен небыл включен sasl.. но теперь другая проблема.. письма приходят, но содержание непонятное.. инфо что коммутатор выключен или включен нет в содержании. как то можно ее исправить
@magomed
Советую смотреть логи openfire и смотреть что показывает при подключении:
# tail -f /var/log/openfire/warn.log
Возможно, что это та же ошибка, что комментарием выше….
Добрый день! как в openfire включить sasl аутетнтификацию? а то из за этого у меня некоторые клиенты не подключаются и с заббикса письма не уходят
Спасибо за статью.
В процессе настройки столкнулся с ошибкой XMPP::Conn: AuthSASL: Authentication failed.
Нашел решение вот здесь http://community.igniterealtime.org/thread/20551
This is a known problem.
At the moment the best you can do is comment out line 1772 in Net/XMPP/Protocol.pm.
The line:
return $self->AuthSASL(%args);
becomes
return $self->AuthSASL(%args);
Not pretty but it works.
Номер строки отличается от описанной в форуме так, что нужно искать строку return $self->AuthSASL(%args); и просто ремить после чего все заработало
Может кому пригодится в процессе настройки.