Telegram давно уже мой основной мессенжер, и вот, решил я разобраться, как отправлять сообщения из CLI себе в клиент TG, а попутно, понял что это можно использовать и как канал уведомлений от mikrotik'ов.
Cначала создаем бота в Telegram
Для этого надо в Telegram найти бота @BotFather,
Далее отправляем команду на создание нового /newbot
,
Называем его как нравится, в данном примере - My CLI Bot.
Следующий вопрос: username для бота. Он должен заканчиваться на bot, и быть уникальным, для этого примера пусть будет mysuper_cli_uniq_test_bot
Итак, мы получили API ключ, который можно использовать дальше.
Есть потребность чтобы бот присылал сообщение не персонально, а в группу, чтобы другие участники могли видеть результаты? Организовываем! Создаем группу, добавляем туда нашего бота, добавляем туда бота RawDataBot, который нам сообщает id нашего группового чата.
В моем случае ответ от бота RawDataBot выглядел вот так:
Так, теперь мы знаем ID чата, (в моем примере: -703498699), и дальше уже добавленного бота RawDataBot можно удалить из группы, а номер чата будем использовать в следующих шагах.
Если группу создавать не требуется, то бот будет присылать сообщения Вам.
Для этого надо открыть диалог с этим ботом, и нажать кнопкуStart
.
А в настройках скриптов указывать в качестве ID номер ID аккаунта в Telegram, узнать его можно у того же бота @RawDataBot.
Отправка сообщений из bash
Самый простой, не особо полезный вариант:
curl -s "https://api.telegram.org/bot5595649065:AAHFJIBbd4a3c1a0cb3a98bjydfgbM1usj3g/sendMessage?chat_id=-703498699&text=simple_text"
Слегка изменим вариант:
curl -s -X POST https://api.telegram.org/bot5595649065:AAHFJIBbd4a3c1a0cb3a98bjydfgbM1usj3g/sendMessage -d chat_id=-703498699 -d text="кое что уже более-менее полезное"
Отправка файла:
curl -F document=@"./Pictures/Screenshot from 2022-07-11 17-13-56-obfuscated.png" "https://api.telegram.org/bot5595649065:AAHFJIBbd4a3c1a0cb3a98bjydfgbM1usj3g/sendDocument?chat_id=-703498699"
Надо либо использовать абсолютный путь, либо относительно текущего каталога, ( ~ не принимается).
Ещё удобнее, если добавить функции в shell.rc файл
Можно ещё упростить жизнь - добавим возможность исполнять желаемое в shell.rc файл (в моем случае это ~/.zshrc, в bash почти так же)
открываем ~/.bashrc (или ~/.zshrc) и добавляем туда вот это:
msg2tg() {
curl -s -X POST https://api.telegram.org/bot5595649065:AAHFJIBbd4a3c1a0cb3a98bjydfgbM1usj3g/sendMessage -d chat_id=-703498699 -d text="$1" > /dev/null 2>&1
}
file2tg() {
curl -F document=@"$1" https://api.telegram.org/bot5595649065:AAHFJIBbd4a3c1a0cb3a98bjydfgbM1usj3g/sendDocument\?chat_id=-703498699 > /dev/null 2>&1
}
После этого в консоли перечитываем rc файл (или открываем новую консоль)source ~/.bashrc
И в итоге можно отправлять сообщения по типу такого:
msg2tg "проверка отправки сообщения из консоли"
msg2tg "`uptime`"
или даже, как например:
msg2tg "`echo "1 BTC = $(curl -s 'https://api.binance.com/api/v1/ticker/price?symbol=BTCUSDT' | cut -d: -f3 | sed 's/"//g; s/}//g') USDT (Binance)"`"
Ну и файлы:
file2tg ./Pictures/429889.jpg
file2tg /var/spool/asterisk/monitor/2022/07/11/_some_name.wav
> /dev/null 2>&1
добавлено для того чтобы возврата результата в консоль не было, для диагностики же полезно бывает видеть ответ от сервера
Не стоит забывать, что для ботов размер отправки файлов ограничен до 50 мегабайт, а сообщений - в количестве знаков. И не более 20 ботов на один аккаунт.
Ознакомиться с ограничениями в целом можно тут, ну и следует почитать и FAQ и документацию по API.
Ещё примеры как это использовать из bash скриптов.
Уведомление о запуске сервера
#! /bin/bash
#license : GNU GPL version 2
#author:
#Telegram Section
TOKEN="5595649065:AAHFJIBbd4a3c1a0cb3a98bjydfgbM1usj3g"
ID="-703498699"
URL="https://api.telegram.org/bot$TOKEN/sendMessage"
#end of Telegram section
MSG="MyServer send hello after start"
curl -s -X POST $URL -d chat_id=$ID -d text="$(echo "$MSG")" > /dev/null 2>&1
Делаем некий after_start.sh
, делаем для этого файла chmod + x
, сохраняем его в какой нибудь типа /usr/local/bin/after_start.sh
,
далее создаем например /etc/systemd/system/msg_after_start.service
, в котором напишем:
[Unit]
Description=User's notification after system boot
After=systemd-user-sessions.service
After=network-online.target
[Service]
ExecStart=/usr/local/bin/after_start.sh
[Install]
WantedBy=multi-user.target
А затем, не забыть ещё включить сервис:
systemctl enable msg_after_start.service
Сбор данных
#! /bin/bash
#license : GNU GPL version 2
#author:
#Telegram Section
TOKEN="5595649065:AAHFJIBbd4a3c1a0cb3a98bjydfgbM1usj3g"
ID="-703498699"
URL="https://api.telegram.org/bot$TOKEN/sendDocument"
#end of Telegram section
tmplog="/tmp/shell_mikrotik_stats_${today}_${RANDOM}"
LC_ALL=C date "+%F %T, %A, UTC %Z" >> "$tmplog"
echo "some_mikrotik_name" >> "$tmplog"
ssh user@some_mikrotik_name '/system resource print; /interface print stats-detail ; /log print ' | egrep -i -A 2 "uptime|lte|vpn" | egrep -v 'info|--' >> "$tmplog"
ssh user@some_mikrotik_name '/ip/dhcp-server/lease/print detail' >> "$tmplog" 2>&1
ssh user@some_mikrotik_name '/log print '|egrep -v "dhcp,info defconf|user user logged|publickey accepted for user" | tail -n 70 >> "$tmplog" 2>&1
curl -F document=@"$tmplog" $URL?chat_id=$ID > /dev/null 2>&1
rm "$tmplog"
После, такой скрипт добавляем к примеру в crontab и получаем искомое с какой-то периодичностью.
Borg Backup с отправкой уведомлений в Телеграм
#!/bin/sh
#Telegram Section
TOKEN="5595649065:AAHFJIBbd4a3c1a0cb3a98bjydfgbM1usj3g"
ID="-703498699"
URL="https://api.telegram.org/bot$TOKEN/sendMessage"
TG_URL2="https://api.telegram.org/bot$TOKEN/sendDocument?chat_id=$ID"
#end of Telegram section
umount /mnt/borg;
today=`date +%Y-%m-%d`
tmplog="/tmp/borg_out_${today}_${RANDOM}.log"
first_day_of_cur_month=`date +%Y%m01`
first_week_of_month=`date -d "$first_day_of_cur_month" +%W`
current_week=`date +%W`
current_week_of_month=`expr $current_week - $first_week_of_month`
#если в момент запуска скрипта на календаре в рамках одного месяца неделя под номером 3, то работаем с одним набором каталогов, если 1 - то с другим.
if [[ "$current_week_of_month" -eq 3 ]] ; then
cd /mnt/smb.server1/share/Пользовательские\ данные;
BackupPath=" Набор1 \
Папка2 \
../Каталог3"
BPreffix='auto-sh-rd-'
elif [[ "$current_week_of_month" -eq 1 ]] ; then
cd /mnt/smb.server2;
BackupPath=" ./"
BPreffix='auto-sh-nd-'
else
BackupPath=" "
exit 0;
fi
# Уведомление в Телеграм о начале работы скрипта
MSG="Backuping by Borg started "$(echo "$today")", in `pwd` for "$(echo "$BackupPath")" "
curl -s -X POST $URL -d chat_id=$ID -d text="$(echo "$MSG")" > /dev/null 2>&1
# Setting this, so the repo does not need to be given on the commandline:
export BORG_REPO=/backup/borg/big-share
# See the section "Passphrase notes" for more infos.
export BORG_PASSPHRASE='=4Na=R>!SD^csp;Kcdc2s&M}?L-W7)2s_gWL54}4!sq6'
# some helpers and error handling:
info() { printf "\n%s %s\n\n" "$( date )" "$*" >&2; }
trap 'echo $( date ) Backup interrupted >&2; exit 2' INT TERM
info "Starting backup"
# Backup the most important directories into an archive named after
# the machine this script is currently running on:
borg create \
--stats \
--verbose \
--filter AME \
--list \
--stats \
--show-rc \
--compression zstd,18 \
--exclude-caches \
--exclude '*.avi' \
--exclude '*.AVI' \
--exclude '*.asf' \
--exclude '*.VOB' \
--exclude '*.MP4' \
--exclude '*.mp4' \
--exclude '*.MPG' \
--exclude '*.MPEG' \
--exclude '*.mpeg' \
--exclude '*.mpg' \
--exclude '*.mov' \
--exclude '*.MOV' \
--exclude '*.webm' \
--exclude '*/Thumbs.db' \
--exclude 'Thumbs.db' \
--exclude '*.tmp' \
\
::$BPreffix'{now}' \
$BackupPath 2>> "$tmplog"
backup_exit=$?
curdate2=`LC_ALL=C date "+%F %T, %A, UTC %Z"`
echo "Backup procedure ended at "$(echo "$curdate2")" " >> "$tmplog"
info "Pruning repository"
# Use the `prune` subcommand to maintain 7 daily, 4 weekly and 6 monthly
# archives of THIS machine. The '{hostname}-' prefix is very important to
# limit prune's operation to this machine's archives and not apply to
# other machines' archives also:
borg prune \
--list \
--prefix 'auto-sh-' \
--show-rc \
--keep-weekly 4 \
--keep-monthly 6 2>> "$tmplog"
prune_exit=$?
#send log and info to Peoples in Telegram Chat
# Так как размер файла получается большой, то сначала сжимаем, а потом сжатое уже отправляется
xz -e -T0 -k $tmplog
curl -F document=@"$tmplog".xz $TG_URL2
MSG1="Backuping by Borg, which started "$(echo "$today")", is ended"
MSG2=`tail -n 60 $tmplog|grep "Backup procedure ended" -B22 -A2`
curl -s -X POST $URL -d chat_id=$ID -d text="$(echo "$MSG2")" > /dev/null 2>&1
curl -s -X POST $URL -d chat_id=$ID -d text="$(echo "$MSG1")" > /dev/null 2>&1
# Remove tmp file
rm "$tmplog"
# use highest exit code as global exit code
global_exit=$(( backup_exit > prune_exit ? backup_exit : prune_exit ))
if [ ${global_exit} -eq 0 ]; then
info "Backup and Prune finished successfully"
elif [ ${global_exit} -eq 1 ]; then
info "Backup and/or Prune finished with warnings"
else
info "Backup and/or Prune finished with errors"
fi
exit ${global_exit}
Настраиваем планировщик на запуск этого скрипта например раз в неделю, и будем получать уведомления в телеграм когда бекап начался, когда закончился, и какие были результаты.
Уведомления от MikroTik-ов (RouterOS)
Ну и тут я вспомнил про уведомления с микротиков, и подумал, может быть полезным..
Открываем WebUI или WinBox, или быть может консоль по ssh, короче заходит на нужный Mikrotik, и после Log in переходим system -> Scripts, создаем новый, назовем его например msg2tg
msg2tg
do {
:global text4tg
:local telegramBotToken "5595649065:AAHFJIBbd4a3c1a0cb3a98bjydfgbM1usj3g";
:local destination "-703498699";
:local requestUrl "https://api.telegram.org/bot$telegramBotToken/sendMessage";
# Тут указывается текст, который будет отправляться.
:local httpData "{\"chat_id\": \"$destination\", \"text\": \"MyHome MikroTik-1 says ::
$text4tg\"}";
/tool fetch url=$requestUrl http-data=$httpData http-header-field=content-type:application/json http-method=post keep-result=no
} on-error={
/log info "msg2tg finished with error";
}
/log info "script for sending msg to tg is finished";
Следует обратить внимание на отправляемый текст, в этом блоке разумно описать название оборудования которое будет высылать уведомления, для того чтобы настроив такое на нескольких, можно было бы различать от которого из них пришло уведомление.
Я для удобства отправляю в две строки.
Таким образом, у нас получился скрипт, который будем вызывать из последующих (так сэкономим байты памяти, да и при необходимости поправить адреса́та будет легко это сделать для всех зависимых потомков).
Теперь, ну пусть будет скрипт для уведомлений о запуске операционной системы:
msg2tg_after_start.rsc
delay 20;
{
:put [global text4tg "HELLO after START "];
/system script run msg2tg;
}
Задержка в начале нужна, чтобы соединения с интернетом уже поднялись, и только уже после этого выполнять отправку сообщения.
И ещё один скрипт, например, для мониторинга за доступностью оборудования:
Check_ip-cams.rsc
:local ipcamGates "192.168.1.100";
:if ([/ping $ipcamGates interval=5 count=3] <=0) do={
delay 180;
:if ([/ping $ipcamGates interval=5 count=6] <=0) do={
delay 300;
:if ([/ping $ipcamGates interval=5 count=10] <=0) do={
/log warning "IP-Cam to Gates is not available";
:put [global text4tg "$ipcamGates in not available for more than 5 minutes "];
/system script run msg2tg;
}
}
};
:local ipcamGarden "192.168.1.101";
:if ([/ping $ipcamGar interval=5 count=3] <=0) do={
delay 180;
:if ([/ping $ipcamGar interval=5 count=6] <=0) do={
delay 300;
:if ([/ping $ipcamGar interval=5 count=10] <=0) do={
/log warning "IP-Cam to Gar is not available";
:put [global text4tg "$ipcamGar not available for more than 5 minutes "];
/system script run msg2tg;
}
};
};
/log info "script for checking available of IP-Cams is finished";
А теперь настроим планировщик. Переходим System -> Scheduler, и создаем новое задание
msg2tg_after_start_plan, где в поле "On Event
" прописываем название созданного скрипта, как это выше было - msg2tg_after_start.rsc
, время запуска (Start Time
), для этого скрипта указываем Startup
, а интервал будет равен 0
, таким образом оно будет запускаться лишь единожды, после старта системы.
Второй план для планировщика, это проверка доступности оборудования, для него мы так же создаем новую запись, где в поле On Event
указываем правильное название для скрипта, а интервал запуска настраиваем например на 1 час.
Теперь, когда вдруг оборудование будет не в сети, то в клиент телеграма прилетит уведомление:
Для начала уже то, что получилось вроде бы хорошо.
Комментарии (10)
RC_Cat
21.07.2022 15:06и дальше уже добавленного бота RawDataBot можно удалить из группы
Я удалил и, как и ожидалось, бот перестал слать сообщения
Andrey053
21.07.2022 16:43+2вместо ... > /dev/null 2>&1
использую опцию curl-а -o, --output Write to file instead of stdout
curl -s -o /dev/null ...
net_racoon
21.07.2022 17:53+1Костыльные костыли. Для мониторинга есть NMS. А всякие скрипты на коленке- это для домашней сети может и ОК, а для корпоративной (любого размера) это превращается в зверя, который потом обрастает еще большими костылями. Не делайте так. Лучше сразу сделать хорошо, чем потом это все разгребать!
typ6o0jiehb Автор
21.07.2022 23:11Конечно костыли, это ни разу не энтерпрайс, решение именно что для дома, как и тутариал - для энтузиастов.
A1EF
21.07.2022 21:12Б - Безопасность
typ6o0jiehb Автор
21.07.2022 23:10В статье токен изменён, да и вообще для этой статьи отдельный бот был создан, как пример.
uhm
21.07.2022 23:35Для "мониторинга оборудования" у Mikrotik есть встроенный Tools > Netwatch, который умеет выполнять произвольную команду при появлении (On Up) или исчезновении (On Down) связи с заданным IP. При его использовании весь длинный скрипт с пингами не нужен, достаточно прописать /tool fetch с разными сообщениями в On Up и On Down.
uoak
22.07.2022 09:08+1А можно вопрос немножко в сторону — как отправлять сообщения с телеграма на почту ? Хочется интегрировать зоопарк мессенджеров в одном месте, причём именно в почте. Пытался гуглить, обычно предлагают либо какие-то боты трёхлетней давности , либо написать такой бот самому… Вдруг есть альтернатива ?
ramiil
Я отправляю сообщения так. Всё работает. Не забудьте объявить переменные $botid, $apikey, $chatid и $message