Bash scripting and cronjobs โฐ
Anything mentioned here can be found in this repository
In this blog post I will show you how do I use multiple bash scripts with cronjobs to monitor a few things of my homelab.
What is cronjob? ๐ค
Cron is a time-based job scheduler in Unix-like computer operating systems. Users that set up and maintain software environments use cron to schedule jobs to run periodically at fixed times, dates, or intervals.
What is bash scripting? ๐ค
Bash is a Unix shell and command language written used by the GNU Project as a free software replacement for the Bourne shell.
Requirements ๐งฐ
- self-hosted server
- telegram account
- curl
Decide what you want to monitor ๐
In this example I will show you how do I monitor one of my services cloudflared
which is a reverse tunnel to my homelab. I want to be notified when something goes wrong with it.
First example ๐
#!/bin/bash
# 0 * * * * alerts
# alias alerts='sh $HOME/scripts/alerts.sh'
TOKEN=""
CHAT_ID=""
echo "๐ Checking if cloudflared is running"
## https://www.cyberciti.biz/faq/systemd-systemctl-list-all-failed-units-services-on-linux/
isRunning=$(systemctl is-active cloudflared)
if [ "$isRunning" != "active" ]; then
echo "๐จ cloudflared is not running"
curl -X POST -H "content-type: application/json" -d "{\"chat_id\": \"$CHAT_ID\", \"text\": \"๐จ cloudflared is not running\", \"disable_notification\": true}" https://api.telegram.org/bot"$TOKEN"/sendMessage
exit 1
fi
echo "๐ Running monitor"
monitor=$(journalctl -u cloudflared -S "$(date -d "-1 hour" +%Y"-%m-%d "%T)" | awk '/ERR/' | tail -n 5)
if [ -z "$monitor" ]; then
echo "โ
No errors found"
exit 0
fi
echo "๐จ Error found"
curl -X POST -H "content-type: application/json" -d "{\"chat_id\": \"$CHAT_ID\", \"text\": \"๐จ Error: $monitor\", \"disable_notification\": true}" https://api.telegram.org/bot"$TOKEN"/sendMessage
At the top of the script we have shebang #!/bin/bash
which tells the system that this is a bash script. Then we have two variables TOKEN
and CHAT_ID
which are used to send messages to telegram. You can get your token from BotFather and your chat id from IDBot. Then we have a few echo
commands which are used to print out some text in the terminal. Then we have isRunning
variable which checks if the service is running. If it's not running then we send a message to telegram and exit the script. If it's running then we run monitor
variable which checks for errors in the last hour. If there are no errors then we exit the script. If there are errors then we send a message to telegram.
Second example ๐
This one is running something like this ->
0 * * * * sh $HOME/scripts/alerts.sh >> $HOME/logs/alert.log
The end result is this ->
The good thing is you can have channels for multiple purposes. These are the ones I have ->
For the backup script I'll do this ->
#!/bin/bash
# Usage 'backup directory/*'
# 0 3 * * 1 backup $HOME/www/*
# alias backup='sh $HOME/scripts/backup.sh'
TOKEN=""
CHAT_ID=""
if [ "$#" -eq 0 ]; then
echo "๐ฉ Usage: $0 directory/*"
exit 1
fi
if ! [ -x "$(command -v curl)" ]; then
echo "โ Error: curl is not installed." >&2
exit 1
fi
# https://unix.stackexchange.com/questions/24630/whats-the-best-way-to-join-files-again-after-splitting-them
date=$(date +%F)
tar -zcvf backup-"$date".tar.gz "$@"
split --bytes=49M backup-"$date".tar.gz
# https://gist.github.com/HirbodBehnam/d7a46fac29f5e1f664d467d5a05620dd
for file in x*; do
echo "๐พ Uploading $file"
curl -X POST -H "content-type: application/json" -d "{\"chat_id\": \"$CHAT_ID\", \"text\": \"Date: $date\nFile: $file\", \"disable_notification\": true}" https://api.telegram.org/bot"$TOKEN"/sendMessage
curl -X POST -H "content-type: multipart/form-data" -F document=@"$file" -F chat_id="$CHAT_ID" https://api.telegram.org/bot"$TOKEN"/sendDocument
done
rm backup-"$date".tar.gz x*
echo "๐ Backup completed!"
Note that I'm compressing the files and then splitting them into 49MB chunks. This is because telegram has a limit of 50MB per file. Then I'm sending the files to telegram. If I need them at one piece I can use cat x* > backup.tar.gz
to join them back.
Conclusion ๐
As you may see this is a very simple way to monitor your services and get notified when something goes wrong. You can use this for anything you want. I'm using this for my backups, services, etc. You can also use this to monitor your server's resources like CPU, RAM, etc. You can also use this to monitor your website's uptime. The possibilities are endless.
Bonus ๐
Want to monitor from outside your infrastructure? You should look into openstatus it has a small free tier, a incredible user experience, incident management and multiple locations to monitor from.