# Bash scripting  and cronjobs

# Bash scripting and cronjobs ⏰

Anything mentioned here can be found in this [repository](https://github.com/jd-apprentice/jd-server)

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 📝

```bash
#!/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](https://t.me/botfather) and your chat id from [IDBot](https://t.me/myidbot). 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 ->

```bash
0 * * * * sh $HOME/scripts/alerts.sh >> $HOME/logs/alert.log
```

The end result is this ->

![img](https://cdn.discordapp.com/attachments/875262629516546089/1198759041523011594/image.png?ex=65c0125b&is=65ad9d5b&hm=1ab149f268ea37b17a3208a3c0c4a9396e65de150bb115c08b35eb8853a36316&)

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

![img](https://cdn.discordapp.com/attachments/875262629516546089/1198759234305802431/image.png?ex=65c01289&is=65ad9d89&hm=b9f443e786713d2f419cfea1f0e4013a5cc85c1219c9ec2e0bdeafa2303f76f4&)

For the backup script I'll do this ->

```bash
#!/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](https://www.openstatus.dev/) it has a small free tier, a incredible user experience, incident management and multiple locations to monitor from.

![img](https://cdn.discordapp.com/attachments/875262629516546089/1198760816103661598/image.png?ex=65c01402&is=65ad9f02&hm=76467b79ca8927b8b98220828235e19bf5ff427073edd29f89d2499867da8719&)
