Telegram Nachrichten mit Bash senden
In diesem Artikel beschreibe ich wie man mit Bash und dem curl Befehl, Telegram Nachrichten senden kann.
Telegram Bot erstellen
Um Nachrichten zu einer Telegram Gruppe oder Kanal zu senden benötigen wir einen Bot. Den erstellen wir mit Telegram. Dazu suchen wir nach @BotFather und klicken dann aud /start
. Wir folgen den Anweisungen um einen Bot zu erstellen. Am Ende erhalten wir ein Access Token mit dem wir uns mit der Telegram API authentifizieren können.
Telegram Kanal erstellen
Als nächstes erstellen wir uns einen Telegram Kanal und fügen den oben erstellten Bot als Mitglied dem Kanal hinzu. Der Bot muss die Möglichkeit haben, Nachrichten zu lesen und zu erstellen.
Kanal ID ermitteln
Jeder Gruppe, Chat oder Kanal hat einen eigenen chat_id
, die wir für den neu erstellten Kanal ermitteln müssen. Dazu schreiben wir mit dem neu erstellten Bot eine Nachricht in diesem Kanal und führen folgenden Befehl in der Konsle aus.
curl -s https://api.telegram.org/bot<YourBOTToken>/getUpdates | jq -r .result[].channel_post.chat.id test.json | sort -u | grep -v null
Die ermittelte chat_id
welche mit -100
anfängt, können wir nun zum senden von Nachrichten an Telegram verwenden. Es gibt eine weitere Möglichkeit die chat_id
zu ermitteln. Dazu melden wir uns an https://web.telegram.org/ an. Geht man dann auf den erstellten Kanal, sieht man in der URI nach dem Route- Zeichen die chat_id
.
Nachrichten an Terlegram mit curl
Der eigentliche curl
Aufruf, um Textnachrichten vom Bot an den Telegram Kanal zu senden, sieht wie folgt aus.
curl 'https://api.telegram.org/bot<YourBOTToken>/sendMessage?chat_id=<channel_id>&text=<text>'
Skript um Nachrichten an Telegram zu senden
Ich habe ein Skript erstellt, welches als erstes Argument den Kanal Namen und als zweites Argument die Telegram Nachricht erwartet. Als erstes Argument kann auch -h
bzw. --help
eingegeben werden, um die Hilfe anzeigen zu lassen. Im Skript müssen die Platzhalter <YourBOTToken>
mit dem Bot- Token, <ChannelID>
mit der ermittelten chat_id
und <ChannelName>
mit dem Namen des Kanals (ohne leerzeichen) ersetzt werden. Das Array channel
kann man beliebig mit weiteren Kanälen erweitern.
#!/bin/bash
# $File: telegram.sh $
# $Author: Marko Schulz <info@tuxnet24.de> $
# $Date: Wed 17 Jan 2024 19:32:46 AM CET $
# $Description: Script to add messages to a defined telegram channel. $
# *******************************************************
# Define the telegram bot token
BOTTOKEN="<YourBOTToken>"
# Temporary file
TEMPFILE="/tmp/$(basename $0 .sh).log"
# Mapping of channel and channel Id. You can add more channels to this array.
# The array key (channel name) must be unique.
declare -A channel
channel[<ChannelName>]="<ChannelID>"
# *******************************************************
# This function display help screen and exit with
# the defined exit code.
#
# @param $1 - Error message
# @param $2 - The exit code (default: 0)
# @return void
#
function help () {
local message=${1:-""}
local ecode=${2:-0}
[ -n "${message}" ] && echo -e "${message}\n"
echo -e "\aUsage: `basename $0` \"channel\" \"text message\""
echo -e " -h|--help - Display this screen"
echo -e " arg1 - The telegram channel"
echo -e " arg2 - The telegram message"
exit $ecode
}
# *******************************************************
# MAIN
# Get a clean exit
trap "rm -f ${TEMPFILE}" EXIT
# Display help if -h or --help was set
if [ "$1" == "-h" -o "$1" == "--help" ]; then
help
fi
# Display error if the defined channel not exists
if [ ! "${channel[$1]+abc}" ]; then
help "No telegram channel $1 found" 1
fi
# Display error if no text was defined
if [ -z "$2" ]; then
help "Add message text as second arguments" 1
fi
# Display error if not two arguments defined
if [ "$#" -ne 2 ]; then
help "You can pass only two argument. For string with spaces put it on quotes" 1
fi
# Add message via telegram api to the defined channel.
# The responce will be saved into TEMPFILE.
curl -s \
-X POST \
-d "text=$2" \
-d "chat_id=${channel[$1]}" \
'https://api.telegram.org/bot'$BOTTOKEN'/sendMessage' >\
${TEMPFILE}
# Get .ok, .error_code and .description from responce
send=$( jq -r .ok ${TEMPFILE} )
code=$( jq -r .error_code ${TEMPFILE} )
desc=$( jq -r .description ${TEMPFILE} )
# Finish with right exit code
[ $send = "true" ] && exit 0 || (
echo "Status: ${code} ${desc}" >&2
exit 1
)
# vim: syntax=bash ts=2 sw=2 sts=2 sr noet
# EOF
Erste Nachrichten mit dem Skript senden
Als ersten parameter geben wir den im Array definierten Kanalname an, als zweiten Parameter geben wir die Nachricht an.
telegram.sh "mychannel" "Hello thats's my first message from `hostname`."
Wir haben auch die Möglichkeit, Unicode in der Nachricht zu verwenden. Dieses Beispiel zeigt eine Nachricht mit den Check Emoji.
icon_ok="`echo -e '\U0002705'`"
telegram.sh "mychannel" "${icon_ok} Service is running"
Anwendungsbeispiel
Hmm, wofür können wir das nun nutzen? Cool wäre, wenn man von Telegram benachrichtigt wird, wenn sich jemand am Server anmeldet. Unter Linux werden beim Login alle Dateien unter /etc/profile.d/
die als .sh
enden, ausgeführt. Da könnten wir nun folgendes Skript erstellen, dass uns bei jedem Login benachrichtigt, ausser die Benutzer die im Array ${exclude[@]}
stehen.
#!/bin/bash
# $File: login-notify.sh $
# $Author: Marko Schulz <info@tuxnet24.de> $
# $Date: Wed 17 Jan 2024 20:12:26 AM CET $
# $Description: Script to send telegram notification on login. $
# *******************************************************
# Define the user, where no message will be send
declare -a exclude=( "nobody" )
# Define the telegram channel
channel="<CHANNELNAME>"
# *******************************************************
# This function checks if a value exists in an array.
#
# @param $1 - Value
# @param $2 - Array
# @return bool
#
function in_array() {
local str=$1; shift
declare -a array=( $( echo $@ ) )
for (( i=0; i<${#array[*]}; i++ )); do
[ "${array[$i]}" = "$str" ] && return 0
done
return 1
}
# *******************************************************
# MAIN
# prepare any message you want
login_ipaddr="$(echo $SSH_CONNECTION | cut -d " " -f 1)"
login_date="$(date +"%e %b %Y, %H:%M:%S")"
login_user="$(whoami)"
# Define a nice emoji, e.g. Warning
emoji="`echo -e '\U00026A0'`"
# For new line I use $'\n' here
message="${emoji} Neue SSH Anmeldung auf `hostname`"$'\n'"Username: $login_user"$'\n'"IP-Adresse: $login_ipaddr"$'\n'"Datum: $login_date"
# Send message to telegram, if loginuser is not in exclude array
if ! in_array "${login_user}" "${exclude}"; then
# Notify only on ssh login
[ -n "${login_ipaddr}" ] && telegram.sh "${channel}" "$message"
fi
# vim: syntax=bash ts=2 sw=2 sts=2 sr noet
# EOF