Drucker an IP-Steckdose per Icinga 2 resetten
Wie faul kann man sein? Die Ausgangssituation ist ein älterer Drucker, der sich softwareseitig immer wieder mal aufhängt, sprich: er ist dann zwar an, doch er ist per Netzwerk nicht erreichbar und macht auch sonst nichts mehr. Das einzige, was in dieser Situation hilft: erst ausschalten, dann anschalten.
Oder richtiger: erst hinlaufen, dann ausschalten, dann einschalten – Nervkram also. Die Idee lag daher in der Beschaffung einer IP-Steckdose, genauer einer EnerGenie EG-PMS2-LAN: einer 6fachen Überspannungsschutz-Steckdosenleiste mit LAN-Schnittstelle, die es ermöglicht, vier der Steckplätze aus der Ferne zu kontrollieren. Das ist erfreulich kostengünstig, konfiguriert ist sie auch schnell, und übers Webinterface lässt sie sich rasch bedienen – aber wer möchte das schon? Das muss doch auch eleganter gehen? Daher installierte ich auf meinem Monitoring-Host das Tool egcfg
, das ich auf GitHub aufstöberte: es dient genau dazu, die vier Steckplätze anzusteuern.
$ git clone https://github.com/unterwulf/egctl.git
$ cd egctl
$ make && make install
Zum Funktionieren benötigt das Tool – es heißt übrigens /usr/local/bin/egctl
– noch ein Konfigfile egtab
, welches in /etc
abgelegt werden will. Hier sind IP-Adresse und Passwort der Steckdosenleiste zu hinterlegen.
# Name Protocol IP Port Password
# ------- -------- --------------- ------- --------
egpms pms20 a.b.c.d 5000 einpasswort
Über die Konsole kann das Gerät nun bereits angesteuert werden. Soll also beispielsweise der vierte Steckplatz eingeschaltet werden und die übrigen drei unverändert bleiben, so wäre hierzu folgender Aufruf nötig:
$ /usr/local/bin/egctl egpms left left left on
Was also soll konkret passieren, wenn der Drucker mal wieder rumspinnt? Steckdose #4 abschalten… Paar Sekunden warten… Und Steckdose #4 dann wieder einschalten. Das passt alles in ein kleines Shell-Script namens Reset_Printer.sh
– ich hab’s noch durch ein paar Debug-Meldungen aufgeblasen und dann in /etc/icinga2/scripts
abgelegt.
#!/usr/bin/env bash
PROG="$( basename $0 )"
DEVICE="egpms"
SOCKET="4"
STATE="$1"
if [ $STATE -gt 0 ] ; then
logger "$PROG: Resetting socket $SOCKET on poweroutlet $DEVICE:"
/usr/local/bin/egctl $DEVICE left left left off
if [ "$?" == "0" ] ; then
logger "$PROG: Turned $SOCKET on $DEVICE OFF; waiting 5 seconds and turning ON again."
sleep 5
/usr/local/bin/egctl $DEVICE left left left on
if [ "$?" == "0" ] ; then
logger "$PROG: Turned $SOCKET on $DEVICE ON again; all done."
else
logger "$PROG: Not successful. Please investigate."
fi
else
logger "$PROG: Not successful. Please investigate."
fi
else
logger "$PROG: Host state is $STATE, nothing to do."
fi
Ist ein EventCommand
hinterlegt, so wird es bei Statusänderung des Hosts ausgeführt – und zwar bei jeder Statusänderung. Deshalb fange ich seitens des Scripts ab, welchen Status mein Host hat, dieser wird nämlich als Argument mit übergeben; und das Script soll nur dann ausgeführt werden, wenn der Drucker ungleich UP
(was einer $host.state_id$ > 0
entspricht) gelistet wird. Ich habe auch kurzfristig mit command = "test $host.state_id$ -eq 0 || /etc/icinga2/scripts/Reset_Printer.sh"
und ähnlichen Scherzen experimentiert, erhielt aber in den Logfiles die lapidare Meldung no such file or directory
, und im Director lässt sich sowas überhaupt nicht anlegen, weil er ein Array draus macht. Aber egal, kann sein, dass es irgendwie geht, ich hab mich nicht wirklich lange damit beschäftigt. Brrr, okay, mein Script muss ich noch als EventCommand
in Icinga 2 erfassen – ich hab das über den Director gemacht, aber geht natürlich auch so.
object EventCommand "event_reset_printer" {
import "plugin-event-command"
command = [ "/etc/icinga2/scripts/Reset_Printer.sh" ]
arguments += {
"-state" = {
required = true
skip_key = true
value = "$host.state_id$"
}
}
}
Zuletzt muss man dem Host nun natürlich diesen Event-Handler verpassen. Das wiederum geht über den Director nicht (dort kann man Services einen Handler zuweisen, aber eben nicht Hosts), weshalb ich den Drucker in Form einer Konfigdatei nach /etc/icinga2/conf.d
geschmissen hab.
object Host "printer" {
import "Old Printer"
display_name = "printer"
address = "w.x.y.z"
enable_event_handler = true
event_command = "event_reset_printer"
}
Grundsätzlich war’s das auch schon. Im Debug-Log lässt sich prima beobachten, ob und wann der Event Handler auf die Reise geschickt wurde, und die Debug-Meldungen des Scripts sorgen für Ausgabe in /var/log/syslog
.
$ icinga2 feature enable debuglog
$ service icinga2 restart
$ multitail /var/log/icinga2/debug.log /var/log/syslog
[2018-03-23 09:34:11 +0100] notice/Checkable: State Change: Checkable 'printer' soft state change from UP to DOWN detected.
[2018-03-23 09:34:11 +0100] notice/Checkable: Executing event handler 'event_reset_printer' for service 'printer'
[2018-03-23 09:34:11 +0100] debug/DbEvents: add eventhandler history for 'printer'
--
Mar 23 09:34:11 monitor nagios: Reset_Printer.sh: Resetting socket 4 on poweroutlet egpms:
Mar 23 09:34:12 monitor nagios: Reset_Printer.sh: Turned 4 on egpms OFF; waiting 5 seconds and turning ON again.
Mar 23 09:34:17 monitor nagios: Reset_Printer.sh: Turned 4 on egpms ON again; all done.
Mir sind die Syslog-Meldungen tatsächlich wichtig, da in Icinga Web 2 nicht ersichtlich ist, ob der Event Handler zuschlug und was er gegebenenfalls gemacht hat – an dieser Stelle ist man vollständig auf Logfiles angewiesen. Kurzum: es funktioniert. Der als DOWN
erkannte Drucker wird hart resettet und funktioniert anschließend wieder; da der nächste state change von DOWN
nach UP
geht, wird das Script dann nicht erneut ausgeführt – wer will sich schon in eine Endlosschleife katapultieren? Jedenfalls ist das eine durchaus nicht uncoole Sache, und mir fallen da spontan noch ein paar Anwendungsbeispiele zu ein…
Hintergrundbild: Generic Screenshot, 2018, 1500x 690px, Bild genauer anschauen – © Marianne Spiller – Alle Rechte vorbehalten