Bash scripting  and cronjobs

Bash scripting and cronjobs

ยท

4 min read

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 ->

img

The good thing is you can have channels for multiple purposes. These are the ones I have ->

img

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.

img

ย