Kategorien
Linux Wissen

Linux – nächtliche Routinejobs per WOL „Wake on LAN“

Irgendwann wächst auch auf Linux Workstation-Systemen die Begehrlichkeit, automatisiert Routinejobs zu starten. Sei es die Reorganisation einer Datenbank, die Durchführung von Systemupdates oder schlichtweg eine Datensicherung.

Naheliegend ist, das in der Nacht per cron-Job zu erledigen. Was wiederum voraussetzt, dass der Computer pausenlos eingeschaltet bleibt, was unserer persönlichen CO2-Bilanz alles Andere als zuträglich ist.

Der nächste Evolutionsschritt sieht dann meistens wie folgt aus:

  1. Der Computer wird von einem anderen System kurz vor Fälligkeit des cron-Jobs per „Wake on LAN“ aufgeweckt
  2. Der cron-Job wird abgearbeitet
  3. Der cron-Job (meistens ein Bash-Script) beinhaltet zum Schluss einen Befehl, der den Rechner wieder runterfährt

Das ist fast(!) perfekt, beinhaltet aber noch einen kleinen Gedankenfehler: Zumindest bei mir kommt es gelegentlich vor, dass ich den Rechner bewusst über Nacht anlasse. Z.B. bei größeren Downloads, Compilerorgien oder nächtlichen Notfalleinsätzen soll natürlich vermieden werden, dass der Shutdown irgendwo „dazwischengrätscht“.

Meine Idee

Wir benötigen also einen Prozess, der wie folgt funktioniert

  1. Ausführung des cron-Jobs
  2. Prüfung, ob der Rechner per WOL eingeschaltet wurde
  3. Wenn er per WOL eingeschaltet wurde, wird er wieder heruntergefahren, ansonsten bleibt er an

Nichts leichter als das!

Grundlegende Idee / das Startscript

Meine Firewall schaltet den Rechner um 01:25 Uhr ein. Bei jedem Systemstart wird überprüft, ob dieser im Zeitfenster zwischen 01:15 Uhr und 01:35 Uhr stattfindet. Falls ja, wird eine temporäre Datei angelegt.

Hier das Script, dass ich unter /root/scripte/wol_check.sh gespeichert habe:

#!/bin/sh
#
# Wenn dieses Script zwischen 01:15 Uhr und 01:35 Uhr ausgeführt wird,
# wird die Datei /tmp/wol_yes angelegt.
#
# Der Cronjob für das Backup erkennt am Vorhandensein dieser Datei, ob
# er den Rechner nach dem Backup herunterfahren soll

stunde=$(date +"%-H")
minute=$(date +"%M")

if [ $stunde -eq 1 ]; then
  if [ $minute -ge 15 -a $minute -le 35 ]; then
    date > /tmp/wol_yes
  fi
fi

if [ -f /tmp/wol_yes ]; then
  echo "Start erfolgte im WOL-Zeitfenster"
else
  echo "Start erfolgte außerhalb des WOL-Zeitfensters"
fi

Um spätere Fehlersuchen zu erleichtern, lege ich die Datei /tmp/wol_yes an, indem ich den aktuellen Zeitstempel hineinschreibe.

Dieses Script soll bei jedem Systemstart ausgeführt werden. Hierfür bedienen wird uns des systemd und erstellen einen Service, den wir unter /etc/systemd/system/wol_check.service (Ubuntu Linux!) abspeichern:

[Unit]
Description=WOL Zeitfenster prüfen.

[Service]
Type=simple
ExecStart=/root/scripte/wol_check.sh

[Install]
WantedBy=multi-user.target

Der Pfad /root/scripte/… muss natürlich und gegebenenfalls angepasst werden.

Aktiviert wird der Service mit

systemctl enable wol_check

Unser Ergebnis lautet jetzt dahingehend, dass wir mit Hilfe der Datei /tmp/wol_yes überprüfen können, ob der Rechner im Zeitfenster zwischen 01:15 Uhr und 01:35 Uhr gestartet wurde.

Existiert die Datei, wurde der Rechner in unserem „Wake on LAN“ Zeitfenster gestartet. Existiert sie nicht, erfolgte der Start zu einem anderen Zeitpunkt.

Der cron-Job

Pünktlich um 01:40 Uhr soll der cron-Job starten. Hier meine crontab:

# Each task to run has to be defined through a single line
# indicating with different fields when the task will be run
# and what command to run for the task
# 
# To define the time you can provide concrete values for
# minute (m), hour (h), day of month (dom), month (mon),
# and day of week (dow) or use '*' in these fields (for 'any').
# 
# Notice that tasks will be started based on the cron's system
# daemon's notion of time and timezones.
# 
# Output of the crontab jobs (including errors) is sent through
# email to the user the crontab file belongs to (unless redirected).
# 
# For example, you can run a backup of all your user accounts
# at 5 a.m every week with:
# 0 5 * * 1 tar -zcf /var/backups/home.tgz /home/
# 
# For more information see the manual pages of crontab(5) and cron(8)
# 
# m h  dom mon dow   command
40 1 * * * /root/scripte/at_night.sh > /var/log/at_night.log 2>&1

Das gestartete Script heißt /root/scripte/at_night.sh und sieht so aus:

#!/bin/sh

HOST=altmetallers_workstation

# Hier steht ein Job, der jede Nacht ausgeführt werden soll

if [ -f /tmp/wol_yes ]
then
  date | mailx -s "$HOST WOL Start, Rechner wird heruntergefahren" meine@email.adresse
  rm /tmp/wol_yes
  sleep 60
  /usr/sbin/shutdown -h now
else
  date | mailx -s "$HOST lief bereits und bleibt eingeschaltet" meine@email.adresse
fi

Das müsste es eigentlich gewesen sein. Wer möchte, kann die Befehlszeilen natürlich auch abhängig vom WOL Start durchführen lassen und muss dafür nur die Befehlszeilen verschieben

#!/bin/sh

HOST=altmetallers_workstation

if [ -f /tmp/wol_yes ]
then
# Hier steht ein Job, der jede Nacht ausgeführt werden soll
  date | mailx -s "$HOST WOL Start, Rechner wird heruntergefahren" meine@email.adresse
  rm /tmp/wol_yes
  sleep 60
  /usr/sbin/shutdown -h now
else
  date | mailx -s "$HOST lief bereits und bleibt eingeschaltet" meine@email.adresse
fi

Eine kleine Spielerei zum Schluss

Wir(!) können die Datei /tmp/wol_yes ebenfalls anlegen und das funktioniert natürlich auch als normaler Benutzer.

Das kann dazu führen, dass jeder, der das Verfahren kennt, einen Shutdown erzwingen kann indem er die Datei manuell erstellt. An anderer Stelle können wir uns das aber auch zu Nutze machen:

Nur mal angenommen, wir haben einen Job zu erledigen, von dem wir wissen, dass er „in etwa“ 3-4 Tage dauert – hier können wir ebenfalls einen Shutdown erzwingen, indem wir die Datei händisch ins /tmp schreiben:

irgendein_befehl_der_drei_tage_dauert ; date > /tmp/wol_yes

Im ungünstigsten Fall läuft der Rechner maximal 24 Stunden länger als nötig 🙂

Schreibe einen Kommentar

Deine E-Mail-Adresse wird nicht veröffentlicht. Erforderliche Felder sind mit * markiert.