Такой метод подходит для домашнего использования или использования в SOHO. На что-то большее данная схема не способна, имейте это ввиду.
Ранее на Хабре уже были статьи на тему СМС информирования, но все сводилось к локальным USB-модемам или сервисам email2sms.
В этой статье будет рассмотрена иная схема взаимодействия. А именно: оборудование Mikrotik выступит в роли GSM шлюза, а Zabbix будет отправлять СМС через терминал.
Что понадобится:
1) Mikrotik 951 серии (активный USB-хаб крайне рекомендуется)
2) USB-модем с сим-картой
3) и развернутый Zabbix-сервер.
А работает это все согласно RFC2217.
Вся конфигурация разбита на 3 этапа:
A) Настройка Mikrotik
B) Работа со скриптом отправки
C) Настройка Zabbix
Наcтройка Mikrotik
К Mikrotik'у подключен USB-модем, произведены базовая настройка и проверка работоспособности модема.
Сразу выясните каналы для отправки СМС. В моем случае это было сделано экспериментально, каналы 1 и 2 отвечают за эту функцию.
В документации к ROS была найдена функция проброса COM-порта по TCP (RFC2217). Она позволяет обращаться к оборудованию за роутером через обычный терминал.
Все параметры интуитивно понятны. Каналы данных SMS Settings и Remote Port совпадать не должны!
Со стороны сетевого оборудования на этом настройка окончена.
Скрипт отправки СМС
В качестве гостевой системы ВМ в моем случае выступает Ubuntu 14.04.2. Так исторически сложилось, с этим приходится жить.
Вы же можете использовать как «железный» Zabbix, так и виртуальный.
Путем чтения тонны инструкций был написан скрипт отправки СМС на Bash сначала в текстовом формате, а следом и в формате PDU. PDU-формат позволяет отправлять СМС в Юникоде, т.е. латинские и кириллические символы (в данном случае только они нас интересуют).
Окончательный вариант скрипта, прилагаемый здесь, позволяет отправлять «многостраничные» СМС любого содержания, т.е. более 70 символов.
Для тех, кто хочет проникнуться, я оставлю несколько ссылок: тык и тык
В случае, если вы хотите проверить работу скрипта из терминала, уберите "-e" у «echo».
#!/bin/bash
#Переменные
tel=$1
header=$2
mes=$3
ip=XXX.XXX.XXX.XXX #IP шлюза
port=Y #Порт шлюза
#Служебные переменные !!! НЕ ТРОГАТЬ !!!
TP_MR0=0 #Начальный параметр TP-MR
IED31=1 #Начальный параметр IED3 для блока UDH
#Начинается...
###########################################################################################################################################
#Переменные для обоих блоков
#Вычисление длины сообщения для определения использовать ли UDH
UDH=`echo $mes | recode ..U2/x2` #Преобразование тела сообщения в UCS2
UDH=`echo $UDH | sed 's/0x\|,\| //g' | sed 's/000A$//g'`
TP_UD=$UDH #TP-UD - кодированное сообщение
UDH=`echo -n $UDH | wc -c | gawk '{print $1}'`
UDH=$(($UDH/4)) #Подсчет символов в сообщении - определяет какой типа отправки использовать
#Кодировка номера в нужный формат
tel="$tel"F""
i=`echo -n $tel | wc -c | gawk '{print $1}'`
i=$(($i/2))
while [ "$i" != "0" ]
do
R=`echo $tel | cut --complement -b '3-12' | rev`
TPTEL="$TPTEL$R"
tel=`echo $tel | cut --complement -b '1-2'`
i=$(($i-1))
done
###########################################################################################################################################
#Если символов 70 и менее!
if [ "$UDH" -le "70" ]; then
#Кодировка сообщения и длины сообщения в UCS2
TP_UDL=`echo -n $TP_UD | wc -c | gawk '{print $1}'` #Вычисление длины сообщения в шестнадцатеричный формат вида XX
TP_UDL=$((($TP_UDL+1)/2))
TP_UDL=`printf '%02x' $TP_UDL | sed 's/[[:lower:]]/\u&/g'` #Тут еще в верхний регистр загоняем для красоты
#Собираем строку для >
TPDU=""0011000B91"$TPTEL"0008AA"$TP_UDL$TP_UD" #Собираем всю строку для >
#Подсчет байтов для AT+CMGS=
Byte=`echo -n $TPDU | cut --complement -b '1-2'` #Убираем первые 2 символов, они не участвуют в подсчете
Byte=`echo -n $Byte | wc -c | gawk '{print $1}'`
Byte=$((($Byte)/2))
#Сама процедура отправки на шлюз. Вроде как поддерживается и RFC2217, и RAW
(
sleep 2
echo "AT+CMGF=0" #1 - Текстовый режим, 0 - PDU режим чтоб он сгорел!!!
sleep 1
echo "AT+CSCS=\"UCS2\"" #Кодировка
sleep 1
echo "AT+CMGS=$Byte" #Передача байта в десятичном виде
sleep 1
echo -e "$TPDU\\032" #Передача закодированной строки + Ctrl+Z
sleep 3 #Спим долго, отчет идет долго
echo -e "\\033" #ESC на всякий случай, чтоб модем не завис в случае ошибки
sleep 3
) | telnet $ip $port #Telnet на шлюз, параметры в самом верху
exit 0
##################################################################################################################################
#Если символов более 70!
else
#Тут временные переменные, нужны для цилка
UDH=$((($UDH/67)+1)) #Превращаем UDH в количество циклов (на 1 больше, чем полных СМС по 67 символов)
IED2=$UDH #Посчитаем количество частей СМСок - параметр для UDH
IED2=`printf '%02x' $IED2 | sed 's/[[:lower:]]/\u&/g'`
#Сама процедура отправки на шлюз. Вроде как поддерживается и RFC2217, и RAW
(
sleep 2
echo "AT+CMGF=0" #1 - Текстовый режим, 0 - PDU режим чтоб он сгорел!!!
sleep 1
echo "AT+CSCS=\"UCS2\"" #Кодировка
sleep 1
#Цикл отправки сообщений AT+CMGS=
while [ $UDH -ne 0 ];
do
#Кодировка сообщения и длины сообщения в UCS2
TPUD=`echo -n $TP_UD | cut --complement -b '269-100000000'` #Отрезаем первые 67 символов для кодирования одного СМС
TP_UD=`echo -n $TP_UD | cut --complement -b '1-268'` #Оставшееся сообщение без 67 символов, будет отрезано в следующем цикле
TP_MR=`printf '%02x' $TP_MR0 | sed 's/[[:lower:]]/\u&/g'` #Преобразуем TP-MR (00, 01 и т.д.)
IED3=`printf '%02x' $IED31 | sed 's/[[:lower:]]/\u&/g'` #Текущая часть СМС - параметр для UDH
UDH_TP_UD=""050003FF"$IED2$IED3$TPUD" #Собираем строку для подсчета длины TP-UDL
TP_UDL=`echo -n $UDH_TP_UD | wc -c | gawk '{print $1}'` #Вычисление длины в шестнадцатеричный формат вида XX
TP_UDL=$(($TP_UDL/2))
TP_UDL=`printf '%02x' $TP_UDL | sed 's/[[:lower:]]/\u&/g'` #Тут еще в верхний регистр загоняем для красоты
TPDU=""0041"$TP_MR"0B91"$TPTEL"0008"$TP_UDL$UDH_TP_UD" #Собираем всю строку для >
TP_MR0=$(($TP_MR0+1)) #Увеличивает $TP-MR0 на 1 для следующего СМС
IED31=$(($IED31+1)) #Увеличиваем номер следующего СМС для UDH
UDH=$(($UDH-1)) #Уменьшаем номер для следующего цикл на один
#Подсчет байтов для AT+CMGS=
Byte=`echo -n $TPDU | cut --complement -b '1-2'` #Убираем первые 2 символов, они не участвуют в подсчете
Byte=`echo -n $Byte | wc -c | gawk '{print $1}'`
Byte=$((($Byte)/2))
#Сама отправке нескольких сообщений на шлюз
echo "AT+CMGS=$Byte" #Передача байта в десятичном виде
sleep 1
echo -e "$TPDU\\032" #Передача закодированной строки + Ctrl+Z
sleep 3 #Спим долго, отчет идет долго
echo -e "\\033" #ESC на всякий случай, чтоб модем не завис в случае ошибки
sleep 3
done
) | telnet $ip $port #Telnet на шлюз, параметры в самом верху
fi
exit 0
#В случае, если вы хотите проверить работу скрипта из терминала, уберите "-e" у "echo"
Вам в скрипте необходимо изменить две переменные на ваши — IP и Port.
В скрипт передаются 3 переменные по порядку: номер телефона, заголовок (не используется, просто Zabbix именно в такой последовательности передает данные в скрипт) и само сообщение. Дополнительно переменные экранировать не нужно, Zabbix это делает сам.
По умолчанию скрипт должен лежать в:
для версии 2.2 — /usr/local/share/zabbix/alertscripts
для версии 2.4 — /usr/lib/zabbix/alertscripts.
Не забывайте дать соответствующие права на файл скрипта!
Настройка Zabbix
На стороне Zabbix'а процедура настройки тривиальна, но я опишу ее еще раз для закрепления.
1) Указываете Способ оповещения
2) Указываете необходимый телефон в профиль пользователя
Телефон вводится в формате 11-значном формате, т.е. 7**********
3) Настраиваете действия на сработавший триггер
Не забывайте, что поле действия «Тема по умолчанию» не учитывается в скрипте, поэтому все необходимое выносите в «Сообщение по умолчанию». Я использую для этого следующую конструкцию: {TRIGGER.NAME} {TRIGGER.DESCRIPTION} {ITEM.NAME} — {ITEM.LASTVALUE}. Она более чем информативна.
Послесловие
Как я и предупреждал в начале статьи, все очень примитивно и для «продакшена» не годится. Но метод позволяет за совсем скромные деньги получать чуть больше оперативной информации от вашей системы мониторинга. За сим разрешите откланяться.
Комментарии (38)
tjomamokrenko
20.08.2015 00:11+1Что автор думает о gammu? А о Kannel?
AcidVenom
20.08.2015 08:32Думает, что это отличные инструменты. Насколько мне известно, они не умеют работать по RFC2217, но все решается использованием ttyd.
Такую связку я не тестировал.AcidVenom
20.08.2015 10:15А нет ttyd для 14.04!
Если кто-нибудь знает утилиту аналогичную ttyd, буду очень признателен.
Roy
20.08.2015 00:12-1А чего бы просто sms сервис не использовать? Тот же sms.ru. И проще и дешевле.
kotomyava
20.08.2015 01:58+1Вероятность недоступности внешнего сервиса всё же куда выше, чем даже такой конфигурации.
Но ещё лучше подключить модем к серверу с заббиксом…
AcidVenom
20.08.2015 07:43Я не использовал этот сервис, как у него с оперативностью? В моем случае СМС доходит в несколько секунд после отправки.
Ну и конечно же момент с отвалом канала связи. В случае со свистком, сам свисток можно научить поднимать свое подключение.
mihmig
20.08.2015 11:34Угу, пользовались. но:
1. Внезапно сообщения перестали приходить на часть операторов (хотя деньги исправно списывались )
2. Техподдержка стала не адекватной — на сайте не отвечают, а звонить на московский номер с 10 до 17 МСК как-то не очень удобно
3. ОПСОСЫ спохватились и ну давай повышать тарифы на такую отправку (по ценам 2000-х)
Пока перешли на другого «провайдера», но вообще перейдём на отправку через модем/android-смартфон.
DarkByte
20.08.2015 12:06Причём на столько дешевле, что аж бесплатно. Если конечно отправлять уведомления только себе. Хотя можно хранить табличку сопоставления номера телефона получателя и его api-key с сайта.
Но почему не воткнуть модем в сам сервере и не подключить модем локально? Если сервер находится удалённо, то при потери канала связи он и до модема по сети не достучится. В таком случае для мониторинга доступности сервера мониторинга можно воспользоваться услугами стороннего сервиса мониторинга доступности.AcidVenom
20.08.2015 12:23Если вопрос адресован мне, то метод статьи рассчитан на совместное использование модема или Заббикс, размещенной в ВМ.
Xeenon
20.08.2015 07:10Микротик же сам умеет смс отсылать, а кроме того у него есть API.
Может попробовать через API микротика рассылать?AcidVenom
20.08.2015 07:38Проблем у микротика 2: только текстовый режим отправки СМС, а значит о кириллице можно забыть, и ограничение в 1 СМС (160 латинских символов). У скрипта таких ограничений нет.
mihmig
20.08.2015 11:37Хм, а пробросить можно вообще любой USB-COM конвертер? было бы неплохо «подцепить» что-то типа такого:
(4 реле 5/220 плюс входные/выходные линии TTL)
kernelchip.ru/Ke-USB24R.php
и перезагружать оборудование в серверной.
(Сам-то микротик вряд-ли создаст модель с одним-двумя 220В реле)AcidVenom
20.08.2015 11:46По идее, если микротик увидит оборудование, то и его можно пробросить.
И так же по идее с этим оборудованием можно будет работать через скрипты самого микротика (в вашем случае перезагрузка по СМС и т.д.)
Нужно пробовать, только такой ответ я могу дать.mihmig
20.08.2015 11:59Я понимаю, надо пробовать втыкать оборудование. Жаль, что если какой-то чип-конвертер не заработает, то с этим ничего не сделать — свои модули к закрытой RouterOS ведь не написать?
А как принять СМС-на микротике? Вычитывать из порта входящие СМС? Но ведь ка каждого Huawei/Zte и проч. свой формат?
ihormanchik
25.08.2015 07:32или учим Zabbix новым трюкам
вы серьезно? такой подход на моей памяти уже используется не меньше 10 лет, не новый он совсем
но за реализацию на баше, конечно, спасибо
по скрипту
это
UDH=`echo $UDH | sed 's/0x//g' | sed 's/,//g' | sed 's/ //g' | sed 's/000A$//g'`
можно заменить на
UDH=`echo $UDH | sed 's/0x\|,\| //g' `
AcidVenom
25.08.2015 09:04Да, заголовок не ахти, признаю.
В сети я встречал только схему с GSM-шлюзом, работало это все так же через терминал. Но реализовано было на PHP и быстро под мои нужды заточить не удалось. Только вот не помню, был ли там PDU с UDH или нет.
Сейчас проверить не могу, но вполне возможно, что там хватитsed 's/, 0x//g'
Перепроверю и отпишусь ниже.
denser
26.08.2015 15:01Спасибо за скрипт — моя реализация через API работает, но кирилица — это неплохо!
Но не подскажете, почему скрипт не отрабатывает?
root@zabbix:~/alertscripts# ./sms_all 7********** "" "123" ./sms_all: line 18: recode: command not found Trying 192.168.*.*... Connected to 192.168.*.*. Escape character is '^]'. AT+CMGF=0 OK AT+CSCS="UCS2" OK AT+CMGS=14 > 0011000B919732155403F30008AA00 +CMGS: 103 OK onnection closed by foreign host.
Настройки поправлены на свой адрес и порт, что видно из лога, но обрывается. На микротике тихо, или нет?
echo: sertcp,info connection to serial remote-access 0.0.0.0:24 from 192.168.*.*:38899 echo: sertcp,debug end of file reading TCP port 24
НОВОЕ: может от того что тестирую в терминале, не убрав -е?AcidVenom
26.08.2015 15:10У вас все отрабатывается на ура, +CMGS показывает номер текущего удачно отправленного сообщения.
А вот Recode вы не поставили. Ну и "-e" нужно убрать, иначе это "-е" полезет в строку >.denser
26.08.2015 19:17Хм, может я не достаточно внимательно прочел статью, но о каком Recode речь?
И может оно и отрабатывает на ура :) но смс мне не пришли, хотя через API прекрасно ходят, ровно как и через winbox если отправить.
НОВОЕ: и ведь невнимательно! Спасибо, что тыкнули носом — незаметная строка оказалась, Ctrl+F рулит )AcidVenom
26.08.2015 19:35Выделил жирным для «внимательных» :)
denser
27.08.2015 07:01Возник вопрос, как сделать перенос строки, если через командную строку?
AcidVenom
27.08.2015 08:29Поясните. Пытаетесь из винды сделать?
denser
27.08.2015 11:39Нет, в терминале убунты, тестирую с русскими символами — всё ОК, интересно как перенести строку в сообщении
./sms_all 7******** "" "пошли<?>домой"
Каой символ вводить, чтобы сработал перенос каретки?tjomamokrenko
27.08.2015 11:51Попробуйте
echo -e "пошли\r\nдомой" | xargs ./sms_all 7******** ""
Lelik13a
Только слабое место в такой конфигурации — если microtick умрёт, или канал до него отвалится, то zabbix никому и ничего не расскажет.
Потому, надёжнее всё-таки слать непосредственно с сервера.
Но и этот вариант интересен для общего развития, спасибо.
AcidVenom
Слабых мест у такой конфигурации куча: от проблем с локальной сетью до занятости модема самим микротиком (мне симулировать пока не удалось).
Но, как я писал в самом начале, этот метод подходит мелким предприятиям особенно в наше время. Мелкий бизнес и так пытается любыми средствами сэкономить, не забывая конечно о хоть каком-то мониторинге и какой-то автоматизации.