Wer regelmäßig Linux Server administriert, wird immer wieder die selben Handgriffe durchführen um sicherzustellen, dass das System wie gewünscht läuft. Sind das nur wenige Systeme, wird das üblicherweise via SSH direkt durchgeführt, da sich die Pflege entsprechender Werkzeuge für die remote Pflege kaum rechnet. Warum also nicht gleich ein Script erstellen welches zumindest die schnell auszuführenden Befehle absetzt und lediglich die wichtigen Daten herausfiltert und anzeigt. Über eine der profile Dateien oder eine bashrc kann das dann direkt bei jeder Anmeldung am System passieren.

Auf einem Linux PC muss man dafür nichts installieren, was nicht auch auf dem zu administrierenden Server existiert. Auf dem Windows PC hilft das Windows Subsystem für Linux, welches ich hier auch zur Erstellung der Grafiken verwenden werde. Ich nutze dafür ein Ubuntu 24.04, welches auch auf meinen Webservern zum Einsatz kommt, so muss ich das fertige Script nach der Übertragung auf den Server nur wenig anpassen. So sollte das in etwa am Ende aussehen:

Ubuntuin der WSL

Windows Subsystem für Linux (wsl)

Wer auf einer Linux Maschine arbeitet, kann diesen Abschnitt überspringen und direkt im Terminal arbeiten, für Windows Maschinen würde ich aber das WSL zum Testen vorschlagen, denn das sollte nicht auf einem produktiven Server gemacht werden. Um die Shells der Distributionen aufzurufen nutze ich das Windows-Terminal, welches sich aus einer mit administrativer Berechtigung gestarteten PowerShell mit WinGet einfach installieren lässt:

winget install Microsoft.WindowsTerminal

Windows-Terminal

Das Terminal bietet Karteikarten um mehrere Shells zu organisieren und lässt neben dem Aufruf von Eingabeaufforderung und Powershell auch den direkten Start der installiereten Distributionen zu

Voraussetzungen für WSL

Windows 10, Version 2004 und höher (Build 19041 und höher) oder Windows 11

WSL-Befehl installieren

Der Befehl wsl.exe --install installiert die WSL mit der Standard-Distribution Ubuntu (reboot erforderlich). Um eine Liste der verfügbaren Linux-Distributionen anzuzeigen, die über den Online-Store heruntergeladen werden können, gibt es den Befehl: wsl --list –online und die lassen sich mit dem Befehl wsl install [Distribution] installieren. Eine Vollständige Anleitung gibt es bei Microsoft.

Wichtig ist dabei die WSL 2 Nutzung für die verwendete Distribution einzustellen. Mit dem Befehl wsl -l -v werden alle installierten Distributionen mit ihrem aktuellen Status und der verwendeten WSL Version aufgelistet. Das Sternchen zeigt dabei auf die Standard Distribution.

WSL-l-v

Mit wsl.exe --set-version [DistroName] 2 wird eine Distribution auf die Version 2 umgestellt, wsl.exe --set-default-version 2 setzt die Version als Standard für alle danach installierten Distributionen und ein wsl.exe --set-default [DistroName] macht die angegebene Distribution zum Standard.

Das Anmeldescript

Erstellt eine neue Datei in eurem Home Verzeichnis und öffnet sie mit eurem präferiertem Editor. Ich nutze dafür Visual Studio Code, VIM, Nano oder MCEdit sind aber auch Optionen.

touch ./welcome.sh
code ./welcome.sh

Begonnen wird mit dem Shebang, welcher in jedes Script in die erste Zeile gehört um sicherzustellen, das die Shell genutzt wird, die mit der Syntax in unserem Script umgehen kann.

#!/usr/bin/env bash

Dann folgt ein Header zur Dokumentation. Wollt ihr euer Script öffentlich zugänglich machen, gehört hinter den Autor noch eine E-Mail Adresse.

# dynamische Message of the day (MOTD) für Ubuntu
# Aufruf in profile (letzte Zeile)
#
# Autor: Christian Schmidt
# Datum: 01. Mai 2026
# Lizenz: GPL-2.0

Das Datum

Mit dem Datumsbefehl date kann das Datum ausgegeben werden. Je nach Lokalisierung gibt das unterschiedliche Ergebnisse, aber wir können ihm Parameter mitgeben um das Ergebnis zu formatieren (siehe man date) und in einer Variablen ablegen:

# Datum und Uhrzeit
DATUM=date +"%A, %e %B %Y"

Der Hostname

Der Hostname kann mit dem gleichlautenden Befehl ausgegeben werden. Ein -f als Parameter gibt den voll qualifizierten Hostnamen (Fully Qualified Domain Name (FQDN)) zurück, welcher sich auch gleich in eine Variable speichern lässt:

# Hostname
HOSTNAME=`hostname -f`

IP Adressen

Hier wird es etwas aufwändiger. Wir müssen nicht nur die richtigen Felder finden, sondern auch den Schnittstellennamen, der uns interessiert. Nutze zunächst den Befehl ip a um eine Ausgabe ählich dieser, mit allen Netzwerkschnittstellen zu erhalten:

IP-a

Da uns das Loopback-Device nicht interessiert, wäre der Name der Netzwerkschnittstelle in diesem Beispiel eth0, die IPv4 Adresse ist die nächste Spalte hinter inet und die IPv6 Adresse befindet sich in der nächsten Spalte hinter inet6. Damit können wir auch diese Daten in je eine Variable schreiben:

# IP Adressen
IPV4=`ip addr show eth0 | grep -vw "inet6" | grep "global" | grep -w "inet" | cut -d/ -f1 | awk '{ print $2 }'`
IPV6=`ip addr show eth0 | grep -vw "inet" | grep "link" | grep -w "inet6" | cut -d/ -f1 | awk '{ print $2 }'`

Der Reihe nach! Befehle können mit dem Pipe Symbol | verkettet werden. Dabei wird ein Kommando links des Pipe Symbols bzw. dessen Ausgabe an das Kommando rechts des Pipe Symbols übergeben. Setzen wir das einmal für die IPv4 Adresse zusammen.

  • ip addr show eth0 gibt uns aus dem oberen Beispiel nur die Schnittstelle eth0 aus
  • grep -vw "inet6" sucht darin jetzt (Parameter -w) nach inet6 und gibt dann aber alles Andere aus (Parameter -v)
  • grep "global" sucht darin jetzt nach global und gibt die Zeile in der das gefunden wird aus
  • cut -d/ -f1 schneidet bis zum Trennzeichen / (-d/) alle Felder bis Nummer 1 (-f1, wir zählen von 0) aus und gibt das Ergebnis aus
  • awk '{ print $2 }' gibt dann daraus das zweite Feld (wir zählen von 1) als Ergebnis zurück Die Befehlskette für die IPv6 Adresse müsstest du dir damit selbst erklären können. Wie bereits beim Datum empfohlen, sieh die einzelnen Befehle im Manual nach (man (Kommando)).

Laufzeit (seit Reboot)

Unter Linux ist alles eine Datei und so lassen sich viele relevante Informationen aus dem virtuellen Prozessdateisystem unterhalb von /proc auslesen. So auch die Uptime aus /proc/uptime. Die Zeit in Sekunden seit dem letzten Start des Systems steht dort im ersten Feld, welches wir zur Errechnung der benötigten Felder nutzen können:

# Uptime
UP0=`cut -d. -f1 /proc/uptime`
UP1=$(($UP0/86400))        # Tage
UP2=$(($UP0/3600%24))      # Stunden
UP3=$(($UP0/60%60))        # Minuten
UP4=$(($UP0%60))           # Sekunden

Letzte Anmeldung

Jede Anmeldung wird mit weiteren Informationen dazu in /var/log/wtmp (ausser Debian 13 Trixie) in Binärform gespeichert, deren Daten das last Kommando bereitstellen kann.

last-2-a

# letzter Login
LAST1=`last -2 -a | awk 'NR==2{print $4}'`    # Wochentag
LAST2=`last -2 -a | awk 'NR==2{print $6}'`    # Tag
LAST3=`last -2 -a | awk 'NR==2{print $5}'`    # Monat
LAST4=`last -2 -a | awk 'NR==2{print $7}'`    # Uhrzeit
LAST5=`last -2 -a | awk 'NR==2{print $11}'`   # Remote-Computer

Wir suchen uns aus dem auf zwei Einträge beschränkten (-2) Ergebnis von last mit awk, aus der zweiten Zeile (NR=2) jeweils ein Feld (print $(Feldnummer beginnend bei 1)) um es in einer Variablen abzulegen. Der Parameter „-a“ veranlasst last dazu den Remotecomputer an die letzte Stelle zu setzen. Auf einem per ssh erreichten System ist das die IP Adresse des sich anmeldenden Benutzers.

Systemauslastung

Die aktuelle Systemauslastung (load average) holen wir wieder aus dem virtuellen Prozessdateisystem, jetzt aus /proc/loadavg. Wenn man es genau nimmt, sollte die Datei nur einmal in eine Variable ausgelesen und dann mit dieser weitergearbeitet werden.

# Durchschnittliche Auslasung
LOAD1=`cat /proc/loadavg | awk '{print $1}'`    # Letzte Minute
LOAD2=`cat /proc/loadavg | awk '{print $2}'`    # Letzte 5 Minuten
LOAD3=`cat /proc/loadavg | awk '{print $3}'`    # Letzte 15 Minuten

Plattenspeicher

Zunächst suchen wir uns aus der Ausgabe des Kommandos df -h einmal die Zeile unseres Root-Verzeichnisses / heraus und merken uns den Namen des Gerätes /dev/xxx. Bei sich drehenden Laufwerken z.B. sda, sdb usw., bei PCIe Laufwerken z.B. nvme0n und bei virtuellen Cloud-Servern auch mal vda. Sind mehrere Laufwerke vorhanden, muss ggf. auch die nachfolgende Zahl mit angegeben werden.

# Speicherbelegung
DISK1=`df -h | grep 'dev/sd' | awk '{print $2}'`    # Gesamtspeicher
DISK2=`df -h | grep 'dev/sd' | awk '{print $3}'`    # Belegt
DISK3=`df -h | grep 'dev/sd' | awk '{print $4}'`    # Frei

Ich habe meinen Devicenamen hier absichtlich verkürzt, da die WSL gerne zwischen zwei Aufrufen die Namen hochzählt und so aus einem zunächst als /dev/sdd erkannten Laufwerks plötzlich ein /dev/sde Laufwerk wird. Da die WSL normalerweise nur ein virtuelles Laufwerk eingebunden hat, sind hier aber damit auch keine Überraschungen zu erwarten.

Hauptspeicher

Erst einmal müssen wir in der Ausgabe des free Befehls nachsehen wie RAM und Auslagerungsspeicher benannt werden um danach suchen zu können. Wie sich die Befehlskette zusammensetzt sollte jetzt nachvollziehbar sein.

# Arbeitsspeicher
RAM1=`free --mega -h | grep 'Speicher' | awk '{print $2}'`    # Total
RAM2=`free --mega -h | grep 'Speicher' | awk '{print $3}'`    # Used
RAM3=`free --mega -h | grep 'Speicher' | awk '{print $4}'`    # Free
RAM4=`free --mega -h | grep 'Auslager' | awk '{print $3}'`    # Swap used

Ausgabe der gesammelten Daten

Eigentlich müssen jetzt lediglich die in den Variablen gesammelten Daten ausgegeben werden.

# Ausgabe des Logos und der erfassten Werte
echo „ $DATUM
 Hostname......: $HOSTNAME
 IP v6 Adresse.: $IPV6
 IP v4 Adresse.: $IPV4
 Uptime........: $UP1 Tage, $UP2:$UP3 Stunden
 Letzter Login.: $LAST1, $LAST2 $LAST3 $LAST4 von $LAST5
 Auslastung..: $LOAD1 (1 Min.) | $LOAD2 (5 Min.) | $LOAD3 (15 Min.)
 Speicher auf /: Gesamt: $DISK1 | Belegt: $DISK2 | Frei: $DISK3
 Hauptspeicher.: Gesamt: $RAM1 | Belegt: $RAM2 | Frei: $RAM3 | Swap: $RAM4“

Dabei läuft das eigentliche Kommando echo über mehrere Zeilen, umfasst nämlich alles zwischen den Anführungszeichen. So lassen sich Linefeed Zeichen ohne die Übersichtlichkeit gefährdende Sonderzeichen bzw. Escape Sequenzen nutzen.

Testen lässt sich das jetzt indem es zunächst einmal ausführbar gemacht und dann aufgerufen wird:

chmod +x ./welcome.sh
./welcome.sh

Einbindung als Logon-Script

Da gibt es mehrere Optionen. Je nachdem ob es für alle oder lediglich bestimmte Benutzer eingerichtet werden soll, muss es unterhalb von /etc oder innerhalb des Home-Verzeichnis jedes Benutzers der es erhalten soll in die profile Datei als letzter Eintrag. Dabei ist darauf zu achten, dass die Datei im Homeverzeichnis versteckt ist, also mit einem Punkt beginnt, im Konfigurationsverzeichnis /etc aber nicht.

profile

Wird nur ein Benutzer dieses Script bekommen, kann es im Homeverzeichnis verbleiben, andernfalls würde ich es in ein allgemein zugängliches Verzeichnis kopieren und den Besitz an root übergeben.

cp ./welcome.sh /var/local/welcome.sh
chown root:root /var/local/welcome.sh

Dann einfach einmal ab.- und wieder anmelden oder eine neue Instanz der bash aufrufen.

Escape Sequenzen

Wem das zu langweilig aussieht, der kann noch Farbe ins Spiel bringen. Wie im ersten Bild des Beitrags zu sehen, habe ich nicht nur Datum und Hostname koloriert, sondern auch das Ubuntu Logo eingebunden. Das ist besonders hilfreich, wenn man viele virtuelle Maschinen mit unterschiedlichen Distributionen verwaltet. Suche im Web einfach nach ASCII Art und deinem Distributionsnamen oder lade dir ein Bild des gewünschten Logos herunter und verfüttere es an einen konvertierenden Dienst. Da gibt es einige, die z.T. auch gleich die Escape Sequenzen für die Farben mitliefern. Anhand von Datum und Hostname zeige ich einmal wie das funktioniert. Für den Rest bist du dann selbst gefragt. Es gibt eine recht Umfangreiche Liste von Escape Sequenzen von ConnerWill auf Github Gists, einschließlich Farbtabelle:

ESCFarbtabelle

Aber zurück zum Script. Zunächst muss dem echo Befehl mitgeteilt werden, dass wir gerne ANSI Escape Sequenzen verwenden würden und er die entsprechend verarbeiten soll. Dazu ändere die erste Zeile des Kommandos wie folgt:

echo -e „ $DATUM

Ich nutze zum Starten einer Sequenz die Oktale Schreibweise \033. Zusammen mit der ID=38 für die von mir für das Datum ausgesuchte Farbe und ID=136 für den Hostname ergibt sich die Sequenz \033[38;5;38m vor dem auszugebenden Datum und \033[38;5;136m vor dem auszugebenden Hostname, sowie \033[0m nach jedem farbigen Text als Reset. Ändere also die ersten zweit Zeilen des echo Befehls wie folgt:

echo -e „ \033[38;5;38m$DATUM\033[0m
Hostname......: \033[38;5;136m$HOSTNAME\033[0m

Nein, Escape Sequenzen machen das ganze nicht übersichtlicher, aber warte ab bis du versuchst das Logo der Distribution farbig hinzuzufügen. Viel Spaß beim Ausprobieren!

Zusatzaufgabe

Das weiter oben verlinkte Gist listet auch die benötigten Escape Sequenzen auf um den Cursor zu verschieben. Damit lassen sich Textausgabe von Variablen und das Distributionslogo im Script voneinander trennen. Das Logo wird zunächst in einem Kommando ausgegeben und die Variablen dann in einem zweiten, wobei der Cursor für jede Textausgabe verschoben werden muss.

Update 8. Mai 2026 11:30 Uhr

Ich habe das vollständige Script für Debian zum Download eingestellt.

 curl https://www.jcs-net.de/downloads/welcome.sh

Fachsimpeln oder Kommentieren gerne im Fediverse.

Vorheriger Beitrag Nächster Beitrag