среда, 21 февраля 2018 г.

Отправка уведомлений сервера в Telegram - не просто, а очень просто

Зачем это надо? - скажете вы. Есть SMS. Есть E-mail.

Ага. Есть.

Для SMS нужен gateway. И иногда весьма прямые руки.

E-mail запросто попадает в спам и вы никогда не увидите уведомлений.

А уведомления бывают важные. Брутфорс-атака на выставленный наружу SSH (вы же, надеюсь, в 2018 году по паролю вход намертво отключили, вы ж не линуксоид, а?). Отказ дисковой системы. Падение критического сервиса.

О таких вещах желательно узнавать чем скорее - тем лучше. Например прямо в мобило, но не по SMS - это нынче не модно, да и дорого. Отправим уведомление прямо в Телеграм (Паша не дурак, у него просто фамилия такая).

Несмотря на попытки некоторых, гм, метросексуалов решать данную задачу вычурными способами, с JSON и прочей веб-содомией, все значительно проще.

Два простых пререквизита.

  1. Вам нужен бот, созданный @BotFather.
  2. Вам нужен chat_id вашего аккаунта в Телеграм. 
"Вот эти ребята" :


"Смотри, не перепутай, Кутузов!" - там есть еще пара-тройка мимикрирующих подобий, рассчитанных на неосторожных ребятишек.

Добавьте своего бота себе и выполните /start.

Теперь для отправки сообщений нужно две простых вещи: security token вашего бота и ваш chat_id (число), полученное у второго бота (строго говоря, его можно вытащить из JSON обмена, через API ботов итп. - но мы же договорились не содомировать).

Напишем крошечный вспомогательный скрипт (по существу, в нем одна-единственная команда отправки текста на интерфейс бота, но сделаем более удобно) для отправки текста, который берется из STDIN, боту:
 #!/bin/sh  
   
 # Access  
 BOT_TOKEN="XXXXXXXXX:XXXXXXXXXXXXXXXXXXXXXXXXXXX"  
 CHAT_ID="XXXXXXXXX"  
   
 # Connect parameters  
 TIMEOUT="10"  
   
 while read TEXT  
 do  
  curl -s --max-time $TIMEOUT -d "chat_id=$CHAT_ID&disable_web_page_preview=1&text=$TEXT" https://api.telegram.org/bot$BOT_TOKEN/sendMessage >/dev/null  
 done < "${1:-/dev/stdin}"  
   

Подставляем наш bot token и свой chat_id. Делаем скрипт исполняемым и помещаем в /usr/local/bin.

Собственно, почти все. Можно протестировать:

 # send-telegram.sh <<EOT  
 Hello!  
 EOT  

Писать по-русски можно, но текст должен быть в UTF-8 (или в ASCII).

Сообщение прилетает практически мгновенно:

Теперь можно засунуть скрипт отправки куда угодно - в SMF, в cron, в другой скрипт.

Для примера, затолкаем его в хорошо известный auth-crit.sh:

 #!/bin/ksh  
 #  
 # written by Michael.Peters@Lazarusalliance.com as part of the  
 # SafetyNET project. Use this to extract information from /var/adm/messages  
 # and email the alert to the administrator.  
 #  
 # Usage: Execute from crontab every 5 minutes  
 #  
 # 4,9,14,19,24,29,34,39,44,49,54,59 * * * * /usr/local/bin/auth-crit.sh > /dev/null  
 #  
 #  
 PATH=/usr/bin:/usr/sbin:/usr/ucb:/bin  
 SRVNM=`uname -n`  
 DATE=`date '+%b %d'`  
 DAY=`date '+%d'`  
 HOUR=`date '+%H'`  
 MONTH=`date '+%m'`  
 MIN=`date '+%M'`  
   
 LOGDIR=/var/adm/crit  
 DATFILE=$LOGDIR/auth-crit.dat  
   
 if [ ! -d $LOGDIR ] ; then  
    mkdir -p $LOGDIR  
    touch $DATFILE  
 fi  
   
 if [ $HOUR -eq "00" ]; then  
   
  if [ $MIN -lt "05" ]; then  
     > $DATFILE  
  fi  
   
 fi  
   
 ### Add your email address below  
 MAILADD=you_email@domain.com  
 MAILFROM=auth_crit  
   
 if [ `grep -c "$DATE $HOUR" $DATFILE` -eq 0 ]  
 then  
     ANSWER=`dmesg | grep -c "$DATE $HOUR.*auth.crit"`  
     if [ $ANSWER -gt 0 ]  
     then  
   
 mail $MAILADD <<EOF  
 From: $MAILFROM  
 To: $MAILADD  
 Subject: auth.crit alert has occurred on $SRVNM  
   
 An auth.crit event has occurred:  
   
 `dmesg | grep "$DATE $HOUR.*auth.crit"`  
   
 EOF  
   
 print "$DATE $HOUR" >> $DATFILE  
   
     fi  
 fi  
   
 # Has a notice been sent this hour?  
 if [ `grep -c "$DATE $HOUR" $DATFILE ` -lt 1 ]  
 then  
   
 if [ `grep "$DATE $HOUR" /var/adm/messages | grep -v auth.crit- | grep auth.crit | grep -c "+" ` -gt 0 ]  
 then  
   
 mail $MAILADD <<EOT  
 From: $MAILFROM  
 To: $MAILADD  
 Subject: auth.crit Alert $SRVNM  
   
 The following auth.crit alert has occurred:  
   
 `grep "$DATE $HOUR" /var/adm/messages | grep auth.crit `  
   
 EOT  
   
 # Send alert to Telegram if script exists  
 # Added by Y.Voinov <yvoinov@gmail.com> at 2018  
 [ -x /usr/local/bin/send-telegram.sh ] && /usr/local/bin/send-telegram.sh <<EOT  
 Subject: auth.crit Alert $SRVNM  
 The following auth.crit alert has occurred:  
 `grep "$DATE $HOUR" /var/adm/messages | grep auth.crit `  
 EOT  
   
 # Make sure notification only occurs once per hour  
 print "$DATE $HOUR auth.crit" >> $DATFILE  
   
 fi  
 fi  
   
 exit 0  
 #  

Теперь, всякий раз, когда cron исполняет скрипт и тот находит что-либо критическое в /var/adm/messages, не только отправляется мэйл админу, который может осесть в спаме, но и уведомление в Телеграм ему же.

PS. Если слегка подумать - это элементарно женится с SYSLOG-сервером, цисками и вообще всем, где можно отправить HTTP(S) запрос.