Send Telegram alerts from your Ubuntu server by creating a Bash script that uses the
curl command to POST JSON payloads to the Telegram Bot API. This approach requires no external dependencies beyond standard Linux utilities, making it ideal for system monitoring tasks like disk space checks or service status updates on headless servers.
Prerequisites and Setup
Before writing any code, you must establish communication between your script and Telegram. This involves two main steps: creating a bot via BotFather and obtaining a chat ID to receive messages.
First, open Telegram and search for
@BotFather. Send the command
/newbot and follow the prompts to name your bot. BotFather will provide a unique
API Token, which looks like
123456789:ABCdefGHIjklMNOpqrsTUVwxyz. Store this securely; anyone with this token can control your bot.
Next, you need a destination chat ID. Start a conversation with your new bot by sending any message. Then, visit the URL
https://api.telegram.org/bot<YOUR_TOKEN>/getUpdates in your browser. Look for the
chat object in the JSON response and copy its
id value. For private chats, this is usually a positive integer. If you are posting to a group, you may need to add your bot as an administrator first.
Core Script Structure
The foundation of the notification system is a Bash script that constructs and sends HTTP requests. Create a file named
notify.sh and make it executable using
chmod +x notify.sh.
Start by defining variables for your credentials. This keeps sensitive data separate from logic and allows easy updates.
#!/bin/bash
BOT_TOKEN="YOUR_BOT_TOKEN_HERE"
CHAT_ID="YOUR_CHAT_ID_HERE"
# Function to send message
send_telegram() {
local message="$1"
# Escape special characters if necessary
# Telegram API supports basic MarkdownV2 or HTML
curl -s -X POST \
"https://api.telegram.org/bot${BOT_TOKEN}/sendMessage" \
-H "Content-Type: application/json" \
-d "{\"chat_id\": \"${CHAT_ID}\", \"text\": \"${message}\", \"parse_mode\": \"HTML\"}"
}
# Example usage
send_telegram "Alert: Disk usage is critical."
This script defines a reusable function
send_telegram. It uses
curl to perform a POST request to the
sendMessage endpoint. The payload is formatted as JSON, including the chat ID, the message text, and the parse mode. Using
parse_mode set to
HTML allows you to use simple tags like
<b> for bold text, making notifications more readable.
Integrating System Data
Notifications become powerful when they reflect real-time system state. You can combine the sending function with common Bash commands to monitor resources. For instance, checking disk usage is a frequent requirement for server maintenance.
You can retrieve the current disk usage percentage for the root partition using
df -h / | awk 'NR==2{print $5}'. This command filters the output to get just the percentage figure. Combine this with your notification function to trigger alerts only when thresholds are crossed.
#!/bin/bash
BOT_TOKEN="YOUR_BOT_TOKEN_HERE"
CHAT_ID="YOUR_CHAT_ID_HERE"
DISK_THRESHOLD=90
check_disk() {
local usage=$(df -h / | awk 'NR==2{print $5}' | sed 's/%//')
if [ "$usage" -gt "$DISK_THRESHOLD" ]; then
send_telegram "Disk Alert: Usage at ${usage}% exceeds threshold."
fi
}
check_disk
In this example, the script extracts the numeric usage value and compares it against a defined threshold. If the condition is met, it sends a specific alert. This pattern can be replicated for CPU load, memory usage, or checking if specific systemd services are active. Always ensure your error handling is robust; if
curl fails due to network issues, the script should log the error rather than silently failing.
For more complex date formatting in your logs or notifications, refer to our guide on
Linux Bash: Convert Date-Time Formats with Ease to ensure timestamps are clear and consistent across different locales.
Scheduling with Cron
To automate these checks, use the
crontab utility. Open the crontab editor with
crontab -e. Add a line to run your script at desired intervals. For example, to check disk usage every 5 minutes, add:
* * * * * /path/to/notify.sh >> /var/log/telegram_notify.log 2>&1
Note that cron jobs run in a limited environment. Ensure your script uses absolute paths for all commands and files. Also, consider adding logging to the end of your script (as shown above) to capture any errors from
curl or permission issues. If you encounter issues with signals interrupting your scripts during execution, see
Troubleshooting SIGINT in Bash Scripts for best practices on signal handling.
Frequently Asked Questions
Why are my Telegram messages not arriving?
Verify that your bot token and chat ID are correct and have not expired or been revoked. Check your internet connection and ensure
curl can reach
api.telegram.org. Also, confirm that you have started a conversation with the bot at least once, as bots cannot initiate messages to users who haven't messaged them first.
How do I handle special characters in messages?
When using
parse_mode set to
HTML or
MarkdownV2, you must escape specific characters like underscores, asterisks, or brackets. Use Bash string manipulation or tools like
jq to properly format the JSON payload before sending it via
curl. Incorrect escaping often results in parsing errors from the Telegram API.
Can I send photos or documents via this script?
Yes, but the method differs slightly. Instead of
sendMessage, you would use
sendPhoto or
sendDocument. You need to attach the file using the
-F flag in
curl to upload the binary data alongside the chat ID and caption. This requires the file to be accessible locally by the script.
Is it secure to store tokens in a Bash script?
Storing tokens in plain text scripts is risky if the file permissions are loose. Set strict permissions using
chmod 700 notify.sh so only the owner can execute it. Alternatively, store the token in a hidden file like
.env in your home directory and source it in the script, ensuring the file itself has restricted read/write access.
How can I debug failed API calls?
Add the
-v flag to your
curl command to see verbose output, including headers and status codes. If the API returns an error code like
400 Bad Request, inspect the JSON structure you are sending. Common issues include malformed JSON syntax or missing required fields like
chat_id.