Inhaltsverzeichnis

Weitere Linbo-Skripte

Welche Clients sind online?

Um festzustlelen, welche Clients derzeit noch online sind, kann man das tool fping benutzen. Dafür nehme ich die workstations-Datei, filtere mit grep alle Zeilen heraus, die auf 0 oder 0; enden, schneide mit cut die IP-Spalte heraus und gebe das Ergebnis an fping weiter. Der Paramter -a zeigt nur die IPs der Rechner, die derzeit erreichbar sind.

cat /etc/linuxmuster/workstations | grep -v '0;$\|0$' | cut -d ";" -f 5 | fping -a 2> /dev/null # IP-basiert
cat /etc/linuxmuster/workstations | grep -v '0;$\|0$' | cut -d ";" -f 2 | fping -a 2> /dev/null # hostbasiert

Feststellen des Betriebssystems

Man kann über das Testen offener Ports versuchen, das laufende Betriebssystems festzustellen. Das ist im allgemeinen zwar keine sichere Methode, da ich aber im Schulnetz die Dienste kenne und gezielt ein- und ausschalten kann, sollte das in der Regel eine solide Erkennung ermöglichen. Um das für das eigene Netz zu planen, kann man mit

nmap $hostname

verschiedene Clients auf offene bzw. geschlossene Ports untersuchen. Dies sollte relativ schnell einen geeigneten Port-Test-Plan ergeben, der zuverlässig zwischen Windows und Linux unterscheidet. Geeignete Ports sind z.B.:

PortDienstOS
2222SSHLinbo
135RPC-DienstWindows
631CupsLinux

Der Befehl zum gezielten Testen eines Ports mit nmap lautet

nmap 10.16.1.2 -p 22 | sed -n 6p bzw
nmap hostname -p 22 | sed -n 7p

sed filtert hier die Zeile heraus, die die Rückmeldung über den abgefragten Port enthält. Wenn man mit Hostnamen arbeitet, gibt es eine zusätzliche Zeile mit dem DNS-Eintrag, daher das 7p. Daraus kann man nun eine einfache Bedingung bauen:

nmap 10.16.1.5 -p 22 | sed -n 6p | grep -c "open" > /dev/null && echo OFFEN || echo GESCHLOSSEN

Es wird also einfach gezählt (grep -c), wie oft das Wort „open“ vorkommt - das Ergebnis ist 0 oder 1. && (und bzw. wenn) || (oder bzw. wenn nicht) verknüpfen den Test mit Befehlen.

Liste aller Räume

Für manche Skripte kann es hilfreich sein, sich die Liste aller Räume ausgeben zu lassen - das ist mit folgender Zeile möglich:

cat /etc/linuxmuster/workstations | grep -v "0$\|0;$\" | cut -d ";" -f 1 | sed '$!N; /^\(.*\)\n\1$/!P; D'

sed ist ein wirkliches Wunderwerkzeug - der letzte Befehl entfernt Duplikate aus der Liste. In den grep-Befehl kann man weitere auszuschließende Räume packen:

cat /etc/linuxmuster/workstations | grep -v "0$\|0;$\|^raum1\|^raum2\|^raum7" | cut -d ";" -f 1 | sed '$!N; /^\(.*\)\n\1$/!P; D'

Um diese Räume in einem Skript abzuarbeiten, kann man das Ergebnis auch in einem **Array** speichern:

<code>
rooms=( $(cat /etc/linuxmuster/workstations | grep -v "0$\|0;$\|^raum1\|^raum2\|^raum7" | cut -d ";" -f 1 | sed '$!N; /^\(.*\)\n\1$/!P; D') )
echo ${rooms[@]}

zeigt nun alle Räume, ein

for room in $rooms ...

arbeitet die Räume ab.

Herunterfahren von Rechnern

Wenn ein Rechner per ssh erreichbar ist, kann man direkt per ssh einen Befehl übergeben.

ssh administrator@$host shutdown /t 0 /s

Falls man keinen passwortlosen Zugang zu den Clients eingerichtet hat, kann man sshpass nutzen, um ein Passwort zu übergeben. Die Option StrictHostKeyChecking no verhindert bei neuen Clients den Abbruch wegen unbekanntem Hosts. Ein kompletter Befehl könnte also heißen:

sshpass -p "<passwort>" ssh -o "StrictHostKeyChecking no" administrator@$host shutdown /t 0 /s && echo "shutdown windows/linux on $host"

Bei passwortlosem Zugang (hier z.B. Linbo) lautet der Befehl:

ssh -o "StrictHostKeyChecking no" -p 2222 $host poweroff && echo "shutdown linbo on $host"

Dies klappt sogar, wenn wie derzeit unter Linbo kein Login auf der Shell möglich ist.

linbo-remote-Probleme

Manchmal geht beim längeren linbo-remote-Aufgaben etwas schief. Da linbo-remote die start.conf-Dateien verändert, bleiben dann evtl. die falschen Dateien zurück und der Benutzer sieht nur ausgegraute Linbo-Buttons und kann nichts tun. Das folgende Skript behebt diese fehlerhaften Verlinkungen

#/bin/bash
# Zurückschreiben etwaiger Linbo-Remote-Verknüpfungen
test linbo-remote -l | wc-l && exit 0 # Sicherstellen, dass kein linbo-remote mehr läuft
cd /var/linbo
for f in $(ls start.conf-* 2>/dev/null); do
  if ! [[ $(echo $f | cut -d "." -f "6") -eq "" ]]; then
    echo "Setze $f zurück auf $(echo $f | cut -d "." -f "1-5")"
    mv -f $f $(echo $f | cut -d "." -f "1-5")
  fi
done

Kleine feine Einzeiler

Die bisherigen Überleungen lassen sich zu einem Einzeiler zusammenfassen, der alle eingeschalteten Rechner samt Betriebssystem ausgibg:

for host in $(cat /etc/linuxmuster/workstations | grep -v '0;$\|0$' | cut -d ";" -f 2 | fping -a 2> /dev/null); do nmap $host -p 2222 | sed -n 7p | grep -c "open" > /dev/null && echo "Auf $host läuft LINBO" || nmap $host -p 135 | sed -n 7p | grep -c "open" > /dev/null && echo "Auf $host läuft WINDOWS" || echo "Auf $host läuft LINUX"; done;

Damit lässt sich das Herunterfahren aller Rechner als Einzeiler realisieren (z.B. als abendlicher cron-job):

for host in $(cat /etc/linuxmuster/workstations | grep -v '0;$\|0$' | cut -d ";" -f 2 | fping -a 2> /dev/null); do nmap $host -p 2222 | sed -n 7p | grep -c "open" > /dev/null && <linbo-shutdown> || nmap $host -p 135 | sed -n 7p | grep -c "open" > /dev/null && <windows-shutdown> || <linux-shutdown>; done;

Möchte man einzelne Rechner auslassen, kann man sie in den ersten grep-Befehl einbauen (z.B. grep -v '0;$\|0$\|admin01\|backupserver' - hier werden die Rechner admin01 und backupserver ausgelassen, \| ist das oder von grep).

Danach kann dann Raum für Raum synchronisiert werden (hier 2 Betriebssysteme):

for room in ( raum1 raum2 raum3 ) do
  linbo-remote -r $room -w 45 -c partition,initcache,sync:1,sync:2,halt
  sleep 1h
done

Ein vollständiges Synchronisations-Skript

Das folgende Skript lässt einzelne oder alle Räume synchronisieren und verbindet das mit ein wenig Logging - dann hat man am Morgen gleich eine Liste der Rechner, von man „nachhelfen“ bzw. nachforschen muss. Für die Einschränkung auf einzelne Räume wird ein zusätzliches grep eingefügt, welches nach dem Raumnamen am Anfang der Zeile sucht (grep „^<raumname>„).

#!/bin/bash
# Dieses Skript fährt Rechner einer Gruppe per ssh herunter,
# synchronisiert danach und loggt fehlerhafte Rechner

log=yosync.log
logfail=yosyncfail.log
echo "Log-Datei: groupsync $1 ( $(date) )" | tee $log

if [ "$1" == "all" ]; then
  rooms=( $(cat /etc/linuxmuster/workstations | grep -v "0$\|0;$" | cut -d ";" -f 1 | sed '$!N; /^\(.*\)\n\1$/!P; D') )
else
  rooms=$1
fi

for room in ${rooms[@]}; do
  echo "Shutdown $room" | tee -a $log
  for host in $(cat /etc/linuxmuster/workstations | grep -v '0;$\|0$' | grep "^$room" | cut -d ";" -f 2 | fping -a 2> /dev/null); do nmap $host -p 2222 | sed -n 7p | grep -c "open" > /dev/null && ssh -o "StrictHostKeyChecking no" -p 2222 $host poweroff || nmap $host -p 135 | sed -n 7p | grep -c "open" > /dev/null && sshpass -p "<ssh-pwd>" ssh -o "StrictHostKeyChecking no" <ssh-usr>@$host shutdown /t 0 /s || sshpass -p "<ssh-pwd>" ssh -o "StrictHostKeyChecking no" <ssh-usr>@$host shutdown /t 0 /s; done;

  echo "Sync $room" | tee -a $log
  linbo-remote -r $room -w 45 -c partition,initcache,sync:1,sync:2,halt | tee -a $log

  echo "--- fertig - warte eine Stunde" | tee -a $log
  sleep 1h
done

echo "ListFailCliens -> FailLog" | tee -a $log
while read line; do
  grep $(echo $line | cut -d " " -f 1) /etc/linuxmuster/workstations | cut -d ";" -f 1-3,5) > $logfail
done < <(grep "Failed" $log)