Ziel des Tutorials

In diesem Tutorial stelle ich euch mein Script vor, das ich benutze um LXC-Container und VMs anhand von HTML-Fehlercodes neuzustarten. Hintergrund ist, dass ich einen Dienst hatte der sich gerne mal bei zu viel Last und zu wenig zugewiesenen Resourcen verabschiedet hatte und einen 503 Bad Gateway produziert hat. Mittels des Scriptes wird der Webserver regelmäßig geprüft und im Falle von zuvor definierten Fehlercodes neugestartet. Bei Bedarf wird eine Mail Notification gesendet.

Requierments

Das ausführende System muss für den Mailversand vorbereitet sein. Ich nutze hierfür postfix. Des Weiteren muss der Zugriff auf das Internet mögich sein, damit der Status-Code abgefragt werden kann und das ausführende System muss auf das Netzwerk zugreifen können in dem sich der Proxmox-Host befindet.

Das Script

Der Dienst besteht aus dem Script selber sowie zwei Config-Files und einem Systemd-Timer und Service.

http-status-checker.sh

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
#!/bin/bash

# Requirements: mailutils, curl

# Load the config file
CONFIG_FILE="/path/to/credentials.conf"
source $CONFIG_FILE

# Load http-code file
HTTP_FILE="/path/to/http_statuscode.conf"
source $HTTP_FILE

# Email to notify
SENT_TO_EMAIL="your-email@domain.com"
FROM_EMAIL="from@domain.com"

for ((i=0;i<${#HTTP_CODES[@]};i++)); do
   HTTP_STATUS=$(curl -o /dev/null -s -w "%{http_code}\n" "${URL[i]}")    
    # Check if HTTP status code is in the list of codes to watch
    for ((j=0;j<${#HTTP_CODES[@]};j++)); do
        if [[ "${HTTP_CODES[j]}" == "$HTTP_STATUS" ]]; then
            # Determine the type of the resource (lxc or qemu)
            if [[ ${LXC[i]} == "YES" ]]; then
                TYPE="lxc"
            elif [[ ${VM[i]} == "YES" ]]; then
                TYPE="qemu"
            else
                echo "Neither LXC nor VM is set to YES for index $i"
                exit 1
            fi

    # Reboot the VM or LXC and send email
    curl -s -X POST -H "Authorization: PVEAPIToken=$API_TOKEN" -H "Content-Type: application/json" -d '{}' "${API_URL}/nodes/${NODE[i]}/${TYPE}/${VMID[i]}/status/reboot"
    # Send Email if machine had http error code
    echo "VM ${VMID[i]} on node ${NODE[i]} has been restarted due to HTTP error $HTTP_STATUS on website ${URL[i]}" | mail -r "$FROM_EMAIL" -s "VM Restarted" "$SENT_TO_EMAIL"  
       fi
    done
done

Neben dem Script gibt es zwei Config-Files. In der ersten http_codes.conf können die HTTP-Codes hinterlegt werden bei denen ein Event ausgelöst werden soll. Der Inhalt der Config sieht so aus:

1
HTTP_CODES=(500 502 503 504)

Eine gute Quelle für die HTTP-Codes und was sie bedeuten gibt es auf Wikipeda. Die zweite Config-File credentials.conf beinhaltet den API-Token und URL zu dem Proxmox-Host und die Nodes die überwacht werden sollen.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
## Configuration file for online_checker.sh
# In this file you need to insert the needed information to watch a site
# You can add a new website by adding new variables with a higher index (e.g., URL3, NODE3, VMID3 for website3)
# Your API_TOKEN needs a "\" before the "!" to escape the exclamation mark

API_TOKEN=yourapitoken
API_URL=yourapiurl

WEBSITE_COUNT=2

URL[1]=http://yourwebsite1.com
NODE[1]=yournode1
VMID[1]=yourvmid1
LXC[1]=YES
VM[1]=NO

URL[2]=http://yourwebsite2.com
NODE[2]=yournode2
VMID[2]=yourvmid2
LXC[2]=YES
VM[2]=NO

Das erstellen von Token für die Proxmox-API und das Steuern der Rechte beschreibe ich in einem weiteren Tutorial ausführlich.

SystemD-Timer und Dienst

Damit das Script ausgeführt werden kann greifen wir auf einen SystemD-Timer check-website.timer zurück. In diesem können wir auch den Prüf-Intervall festlegen:

1
2
3
4
5
6
7
8
9
[Unit]
Description=Runs check-website every 5 minutes

[Timer]
OnBootSec=5min
OnUnitActiveSec=5min

[Install]
WantedBy=multi-user.target

Der Timer wird anschließend mittels SystemD-Service check-website.service gestartet und auch bei Bedarf gestoppt:

1
2
3
4
5
[Unit]
Description=Check website status

[Service]
ExecStart=/path/to/your/script.sh

Nachdem ihr den Timer und Dienst erstellt habt, müsst ihr die SystemD-Config mittels sudo systtemctl daemon-reload neuladen, enablen und starten. Das macht ihr am besten mit sudo systemctl enable --now check-website.timer. Wenn man mit einem Timer arbeitet muss nur der Timer gestartet werden, der Timer triggert anschließend den Service. Ist in dem Timer, unter [Timer] keine Unit= definiert wie in diesem Fall, müssen die Timer-Unit und Service-Unit den gleichen Basis-Namen tragen.

Fandest du diesen Artikel hilfreich? Dann freue ich mich über einen Kaffee! ❤️