Seite wählen

NETWAYS Blog

atexit, oder wie man Python-Dienste nicht beenden sollte

Wer schon einmal einen Dienst mit Python realisiert hat, wird bereits vor der Aufgabe gestanden haben die Aufgaben die er verrichtet sauber und geordnet zu beenden. Python bietet einem hier vielerlei Lösungen an, darunter auch das atexit Modul. Für schnelle und simple Aufräum-Arbeiten ist dieses Modul wunderbar geeignet, nicht jedoch wenn Thread-Synchronisation und externe Kommunikation im Spiel ist. Warum das so ist und was die saubere Alternative ist, darum geht es heute in diesem Blogpost.
Wie der Name des Moduls und dessen Dokumentation bereits sagt, werden registrierte Routinen ausgeführt kurz bevor der Interpreter angehalten wird. Klingt erst einmal nicht besonders problematisch, ist es doch gerade was man haben möchte. Und es funktioniert sogar, solange keine Threads laufen. Dann werden die registrierten Routinen nicht aufgerufen. Das liegt daran, dass „normale“ Threads explizit beendet werden müssen, sonst verhindern diese den Stopp des Interpreters. Damit das nicht passiert, kommt man möglicherweise auf folgende Idee:
[sourcecode language=“python“ wraplines=“false“ collapse=“false“]
t = threading.Thread(target=func)
t.daemon = True # Avoids that python hangs during shutdown
t.start()
[/sourcecode]
Ganz schlecht. Das mag möglicherweise den gewünschten Effekt haben und die Aufräum-Routinen können ihre Arbeit verrichten. Aber tatsächlich ist dies nur eine Lösung für ein Symptom, das eigentliche Problem ist noch immer nicht gelöst. Das wird einem spätestens klar, wenn es nicht mehr nur darum geht Threads zu beenden, sondern auch noch mit anderen über das Netzwerk verbundenen Diensten/Klienten eine saubere Unterbrechung der Kommunikation einzuleiten.
Denn was genau passiert wenn der Interpreter angehalten wird?

  1. Der MainThread wird sofort angehalten
  2. Offene File-Handles werden geschlossen
  3. Es wird gewartet dass alle nicht-Daemon Threads beendet wurden
  4. Die atexit-Routinen werden ausgeführt
  5. Garbage Collection
  6. Der Prozess wird beendet

Der zweite Punkt lässt einige vielleicht bereits aufhorchen, denn sockets sind nichts anderes als File-Handles. Wer nun immer noch denkt er könne in einem daemon-Thread die Netzwerk-Kommunikation mit seinem Gegenüber sauber beenden, ist auf dem Holzweg. Zum Zeitpunkt zu dem die atexit-Routinen laufen, sind bereits alle sockets unwiderruflich geschlossen.
Angenommen der Stopp des Dienstes wird ganz normal über SIGTERM initiiert, so könnte man nun alle atexit-Routinen in einen Signal-Handler verlagern. Dadurch würden sie laufen noch bevor der Interpreter angehalten wird, allerdings kommt man so sehr schnell wieder in die Bredouille, je nachdem welche Art von Arbeit der MainThread verrichtet. Denn da Signal-Handler asynchron im MainThread ausgeführt werden, ist das Risiko für ein Deadlock sehr groß. Kommen wir also zur erwähnten, sauberen Alternative: Feuer mit Feuer bekämpfen.
Was vormals in etwa so aussah:
[sourcecode language=“python“ wraplines=“false“ collapse=“false“]
class SomeDaemon:
def start():
# …
signal.signal(signal.SIGTERM, self._sigterm)
atexit.register(self._atexit)
# …
def _sigterm(self, signum, frame):
sys.exit(0)
def _atexit(self):
# Alle Aufräum-Arbeiten
[/sourcecode]
Kann ganz einfach, mit durchschlagendem Erfolg, so umgebaut werden:
[sourcecode language=“python“ wraplines=“false“ collapse=“false“]
class SomeDaemon:
def start():
# …
signal.signal(signal.SIGTERM, self._sigterm)
atexit.register(self._atexit)
# …
def _sigterm(self, signum, frame):
threading.Thread(target=self._cleanup, name=’CleanupThread‘).start()
def _cleanup(self):
# Komplexe Aufräum-Arbeiten
def _atexit(self):
# Einfache Aufräum-Arbeiten
[/sourcecode]
Der „CleanupThread“ sollte selbstverständlich keine Arbeit verrichten die unkontrolliert blockt. Denn dann sieht das ganze am Ende wieder so aus:
[sourcecode language=“python“ wraplines=“false“ collapse=“false“]
def _sigterm(self, signum, frame):
t = threading.Thread(target=self._cleanup, name=’CleanupThread‘)
t.daemon = True
t.start()
[/sourcecode]
Und der ganze Spaß geht von vorne los..

Johannes Meyer
Johannes Meyer
Lead Developer

Johannes ist seit 2011 bei uns und inzwischen, seit er 2014 die Ausbildung abgeschlossen hat, als Lead Developer für Icinga Web 2, Icinga DB Web sowie alle möglichen anderen Module und Bibliotheken im Web Bereich zuständig. Arbeitet er gerade mal nicht, macht er es sich bei schlechtem Wetter am liebsten zum zocken oder Filme/Serien schauen auf dem Sofa gemütlich. Passt das Wetter, geht's auch mal auf eines seiner Zweiräder. Motorisiert oder nicht.

Webinare im Mai

NETWAYS Webinare Nachdem der Webinar-Marathon im April fast zuende geht und das Vagrant Webinar kurz bevor steht, möchte ich natürlich gleich auf die nächsten Webinare im Mai hinweisen. Einerseits geht es dann um unsere Cloud-Lösungen welche wir über unsere Rechenzentren anbieten und einmal um das Thema Windows Vorbereitung für Puppet. Bei dem Windows Webinar liegt der schwerpunkt darauf, wie ein Windows-System soweit vorbereitet werden kann, dass sowohl eine automatische Installation über Images aber auch die anschließende Konfiguration mit Puppet möglich ist. Christoph hatte hierzu bereits einen interessanten Blog-Artikel veröffentlicht.
Zusammengefasst noch einmal die Themen, die Termine und Anmeldelinks im Überblick:

Titel Zeitraum Registrierung
Vagrant: Virtualisierungs Wrapper 30. April 2015 – 10:30 Uhr Anmelden
NETWAYS Cloud Lösungen 08. Mai 2015 – 10:30 Uhr Anmelden
Windows: Vorbereitung für Puppet 22. Mai 2015 – 10:30 Uhr Anmelden

Vorab natürlich eine schöne Restwoche!

Christian Stein
Christian Stein
Manager Sales

Christian kommt ursprünglich aus der Personalberatungsbranche, wo er aber schon immer auf den IT Bereich spezialisiert war. Bei NETWAYS arbeitet er als Manager Sales und berät unsere Kunden in der vertrieblichen Phase rund um das Thema Monitoring. Gemeinsam mit Georg hat er sich Mitte 2012 auch an unserem Hardware-Shop "vergangen".

Reminder für das morgige RT-Webinar!

Morgen um 10:30 Uhr werden Marius und ich die Open Source Ticket Lösung Request Tracker in unserem Webinar vorstellen und sowohl die Vorteile als auch die Flexibilität demonstrieren.
Wer also noch teilnehmen möchte, sollte sich jetzt schnell registrieren, bevor alle Plätze vergeben sind!
Eine vorab Vorbereitung ist zwar nicht notwendig, aber in einem früheren Blog-Artikel zum RT, hatte ich bereits versucht einige Vorteile heraus stechen zu lassen. Um die 24 Stunden bis zum Webinar noch zu verkürzen, lohnt es sich natürlich direkt in unserem Webinar Archiv vorbeizuschauen.
Bis morgen!

Christian Stein
Christian Stein
Manager Sales

Christian kommt ursprünglich aus der Personalberatungsbranche, wo er aber schon immer auf den IT Bereich spezialisiert war. Bei NETWAYS arbeitet er als Manager Sales und berät unsere Kunden in der vertrieblichen Phase rund um das Thema Monitoring. Gemeinsam mit Georg hat er sich Mitte 2012 auch an unserem Hardware-Shop "vergangen".

Neu im NETWAYS Portfolio – Puppet Starterpaket

Puppet_LogoBei Puppet handelt es sich um ein OpenSource Konfigurationsmanagement System, welches vom amerikanischen Unternehmen PuppetLabs entwickelt wird.
Puppet bietet den Vorteil, Administratoren bei z.B. regelmäßigen Aufgaben wie Paketinstallation, Serverinstallationen oder Konfigurationsänderungen zu entlasten.
Das gesuchte Stichwort heißt: Automatisierung.
Um Unternehmen beim Einstieg in die Puppet-Welt zu unterstützen, bieten wir seit einiger Zeit das Puppet Starterpaket in zwei Varianten an:
Puppet Starterpaket Standard
Dieses Paket besteht aus einem 4-Tages-Workshop mit einem unserer Puppet-Consultants, welcher eine Evaluierung einer vorhanden IT-Umgebung vornimmt und anschließend eine mögliche Konzeptionierung aufzeigt, um Puppet erfolgreich zu implementieren. Anschließend wird der Puppet-Master sowie ein Versionskontrollsystem (z.B. SVN, Git, etc.) installiert, um Änderungen an den Puppet-Modulen nachzuvollziehen. Für einen noch besseren Einstieg, werden zusätzlich einige Beispielmodule erstellt, welche im späteren Verlauf natürlich weiter angepasst werden können.
Puppet Starterpaket Premium
Für komplette Einsteiger im Puppet-Bereich, die bisher noch keine persönlichen Berührungspunkte hatten, bieten wir im Premium-Starterpaket zusätzlich zu den 4 Workshop-Tagen noch 3 Tage Vor-Ort Schulung für 3 Teilnehmer an (weitere Teilnehmer gegen Aufpreis möglich).
Die Schulungsinhalte werden 1:1 von unserer Puppet Fundamentals-Schulung übernommen, inkl. Schulungsnotebooks, Schulungsunterlagen sowie ein Teilnehmerzeugnis.
Je nachdem wie komplex die Umgebung und die jeweiligen Anforderungen an das Puppet-System sind, können folgende Themen im Rahmen des Workshops noch mit aufgenommen werden:

  • Einrichtung von Foreman
  • Einrichtung der PuppetDB
  • Anbindung von externen Datenquellen

Selbstverständlich unterstützen wir auch bei individuellen Anfragen zum Thema Puppet oder beim Betrieb einer bereits vorhanden Puppet-Umgebung, auf Basis unserer Supportverträge oder von Consulting-Dienstleistungen.
Für einen persönlichen Kontakt stehen wir ebenfalls sehr gerne zur Verfügung – weitere Details für eine Kontaktaufnahme sind in unserem Kontaktformular zu finden!

Christian Stein
Christian Stein
Manager Sales

Christian kommt ursprünglich aus der Personalberatungsbranche, wo er aber schon immer auf den IT Bereich spezialisiert war. Bei NETWAYS arbeitet er als Manager Sales und berät unsere Kunden in der vertrieblichen Phase rund um das Thema Monitoring. Gemeinsam mit Georg hat er sich Mitte 2012 auch an unserem Hardware-Shop "vergangen".

"Der Checker"

Als NETWAYS schreiben wir uns selbst ein sehr hohes Icinga/Nagios KnowHow auf die eigene Fahne. Aber auch wir haben, wie 99,99% aller Icinga/Nagios Anwender, immer wieder den ein oder anderen Fallstrick zu bewältigen.
Ein Problem, welches sehr häufig Auftritt, das richtige maskieren von Sonderzeichen in Check-Definitionen.
Ein ganz simples Beispiel: Mit wie vielen Backslashes (\) muss man die Pfadangaben eines Shares maskieren, damit Icinga/Nagios diese richtig interpretiert?
Wie ist das vorgehen in einem solchen Szenario? Richtig, man ändert so lange und so oft die Definition, führt jedes mal einen Icinga/Nagios Reload aus und führt den Check neu aus bis man irgenwann das gewünschte Ergebnis hat… Das dies mitunter längere Zeitspannen in Anspruch nimmt ist vielen durchaus bewusst, uns auch!
Icinga/Nagios besitzt im Core ca. 10 Zeilen, welche für das maskieren von Sonderzeichen verantwortlich sind. Dieses kleine Snippet/Wrapperplugin hilft uns nun dabei unsere Checks im vorhinein schon richtig zu bauen und zu testen, um sie anschließend in die jeweilige Definition zu übernehmen.
Ein Aufruf des Wrapperplugins sieht wie folgt aus:

# ./check_executor /opt/icinga/libexec/check_http -H icinga -u "/icinga-web"
Executing command /opt/icinga/libexec/check_http -H icinga -u /icinga-web
Check output: HTTP OK: HTTP/1.1 301 Moved Permanently - 305 bytes in 0.001 second response time |time=0.001075s;;;0.000000 size=305B;;;0

Executing command gibt den eigentlichen Pluginaufruf aus, wie er duch Nagios/Icinga ausgeführt wird.
Check output beschreibt die eigentliche Ausgabe, wie sie u.a. auch in der Weboberfläche sichtbar wäre.
Zu finden ist das ganze in unserem GIT: https://git.netways.org/plugins/collection/trees/master/plugins/check_executor
Um Verwechslungen grundsätzlich aus dem Weg zu gehen: „Der Checker“ kümmert sich natürlich um schöne Autos, unser „Checker“ um Icinga/Nagios Plugins.