Select Page

NETWAYS Blog

Azubis erzählen: März 2015 Jean

This entry is part 7 of 17 in the series Azubis erzählen

Name: Jean-Marcel Fach
Ausbildungsberuf: Fachinformatiker für Anwendungsentwicklung
Abteilung: Icinga2 core development
Lehrjahr: 1

Hallo,
ich schreibe hier als Azubi im Development einen Blogppost zur Serie “Azubis erzählen”. Dieser ist nach diesem Absatz auch zu lesen, aber zunächst werde ich vorstellen.
Ich bin 21 Jahre alt und arbeite seit einem halben Jahr bei Netways. Vorher war ich Student an der Erlanger Universität. Meine Aufgaben haben fast immer mit Icinga 2 zu tun, hin und wieder müssen auch sonstige Aufgaben erledigt werden, mal mehr programmiertechnischer Natur und mal weniger.
Eine dieser Aufgaben war das Script, das das Vorkommen eines Datums in einer Tabelle zählen sollte, doch bevor ich mich damit beschäftigen konnte musste ich erst einmal dafür sorgen das die richtige Datei geöffnet wird. Die Dateinamen sind etwa so kodiert:
NAME_DATUM_UHRZEIT_NUMMER.ENDUNG

rx

Die Matrix war ein Perl Programm. Deswegen machen die Nachfolger auch so wenig Sinn


Wichtig sind dabei eigentlich nur Datum und Uhrzeit, doch wie unterscheidet man diese von den übrigen Teilen des Dateinamens?
Unterstriche zählen fiel als Erstes weg, da der NAME meist selbst noch Unterstriche enthielt. Also muss rückwärts gesucht werden. die Endung erkennt man daran, dass ein Punkt vor ihr steht… leider kann so eine Datei auch mehrere Endungen haben, etwa .txt.gz für komprimierte Dateien. Und wenn der NAME dann selbst einen Punkt enthalten kann…
Also musste eine andere Lösung her: regex
Die regular expression
Lange war ich etwas eingeschüchtert von regex, oft sah ich nur Monster wie dieses hier (Soll Email Adressen validieren, und ist dabei nicht einmal 100% korrekt, wenn man es genau nimmt) und wer will schon mit so einer Wand Text arbeiten müssen?
Also Augen zu und durch, anhand dieses Tutorials brachte ich mir also die regex Grundlagen bei, denn zum Lernen ist hier immer Zeit. Gar nicht mal so schwer, zum Glück gibt es dann noch diese Seite auf der man nach Herzenslust ausprobieren kann.
Nun aber zu meinem konkreten Problem:
deq_2214_20140415_140857_0413.txt.gz
Nach dem Muster oben ist klar, dass es sich um eine verpackte Textdatei, die 413te am 15.4.2014 aus der Serie ‘deq_2214’, gespeichert um 14:08:57, handelt. Aber selbst wenn man das Muster nicht schon vorher kennt ist es leicht es zu erkennen, für einen Menschen. Für einen Computer eben nicht (Daher sind Computer Menschen in Go noch unterlegen, während sie im Schach unschlagbar sind).
Aber ein dummer Computer kann gut stur Schemata überprüfen:
(\w+)_(\d{8})_(\d{6})_(\d{4})(\.txt)(\.gz)?$
Ist die Lösung, Erklärung:

(\w+)    # Fasse den Anfang zu einer Gruppe zusammen ("deq_2214")
  _      # Unterstriche dienen als Abtrennung und werden übergangen
(\d{8})  # Eine Gruppe aus genau acht Zahlen, das Datum ("20140415")
  _
(\d{6})  # Eine Gruppe aus genau sechs Zahlen, die Uhrzeit ("140857")
  _
(\d{4})  # Eine Gruppe aus genau vier Zahlen, die Nummer ("0413")
(\.txt)  # Die Endung ".txt"
(\.gz)?  # Die optionale Zusatzendung ".gz"
  $      # Sorgt dafür das nach der Endung nichts mehr kommen kann
         # (".txt.gz.temp" ist ungültig)

Freie Fahrt für die Ampeln

galleryIMG56431_modSeit längerem gibt es im Netways Shop schon diese kleinen USB Ampeln , doch mit Icinga2 wollten sie nicht leuchten. Nicht einmal rot.
Mit diesem neuen Python Skript aber schon! Und dabei läuft es nicht einmal Gefahr Cthulhu zu beschwören, es funktioniert nämlich gänzlich ohne regex-HTML-parser.
Die Anforderung auf eine Icinga classicUI bleibt leider bestehen, zumindest bis zum Icingaweb2 release.
Ein kleiner Bonus noch für diejenigen mit Ampel aber ohne Icinga, die Disco Ampel:

#!/bin/bash
while true
do
    for i in 0 1 2
    do
        clewarecontrol -as $i 1 1&2> /dev/null
        sleep 1
    done
    for k in 0 1 2
    do
        clewarecontrol -as $k 0 1&2> /dev/null
        sleep 1
    done
done

Der Metazirkulare Evaluator

Hallo, ich bin der neue hier. Und als neuer habe ich erstmal nicht das know how um sinnvolle Infos über firmenrelevante Dinge zu verbreiten. Daher kommt jetzt sinnfreie und absolut unrelevante Information mit der ich mich in meiner Freizeit etwas beschäfftigt habe, und zwarin einer Qualität über die ich hoffentlich in paar Jahren lachen kann.
Programmierung wäre langweilig wenn sie immer simpel und leicht verständlich wäre, deswegen ist wohl auch die Dokumentation vieler Programme so schlecht. Und deswegen erfreut sich das Buch Structure and Interpretation of Computer Progams so großer Beliebtheit. Im folgenden möchte ich mich oberflächlich mit dem Kapitel zum Metazirkularen Evaluator beschäftigen. Dieses Kapitel eignet sich sehr gut um sich an den Interpreterbau heran zu führen doch leidet es sehr unter schweren Verständlichkeit der gewählten Programmiersprache und dem geforderten Vorwissen aus früheren Kapiteln. Daher versuche ich hier möglichst viel weg zu lassen und nur das Nötigste an Fällen und Typen zu schildern.
Trotz seines beeindruckenden Namens ist das Prinzip des Metazirkulare Evaluators simpel, er besteht aus eval, dem Auflösen von Ausdrücken, und apply, dem Auflösen von und Ausführen von Prozeduren (Funktionen ohne Rückgabe).
eval erhält einen Ausdruck und dessen Umgebung (lese: Sichtbarkeit/scope) in der Form eval(Ausdruck, Umgebung), je nach Typ des Ausdrucks wird dann vorgegangen. Hier behandle ich nur die Grundlegenden Fälle, im Buch finden sich weitere und es können auch beliebig viele hinzugefügt werden, diese verhalten sich dann analog. In folgenden sind fünf dieser Möglickeiten für eval:

    1. Der Ausdruck ist ein primitiver Wert, etwa eine Zahl oder ein String, dann wird dieser einfach so zurück gegeben.
      eval(5, foo) --> 5
      eval("Baum", foo) --> Baum
    2. Der Ausdruck ist eine Zuweisung oder Definition, entsprechen werden diese dann gesetzt.
      eval((c = 20), foo) --> c in foo = 20
      eval((define add(arg1, arg2): arg1 = arg1 + arg2), foo) -->
      Erstellt Funktion in bar die ein Argument addiert auf ein anderes addiert
    3. Der Ausdruck ist eine Variable, dann wird der entsprechende Wert wert zurück gegeben.
      eval(c, foo) --> 20
    4. Der Ausdruck ist eine Sequenz, also ein Befehl , dieser wird dann Operation für Operation evaluiert
      eval(arg1 = arg1 + arg2, foo) ---> arg = wird als Zuweisung erkannt,
      arg1+arg2 ist eine Prozedur

      eval(arg1 = eval(arg1 + arg2, foo), foo) ---> rekursiv weiter aufgerufen
      eval(arg1 = apply(+, eval(arg1, foo), eval(arg2, foo))) -->
      Bis nur noch primitive Ausdrücke stehen
    5. Der Ausdruck ist ein Prozeduraufruf, dann wird apply für diese Prozedur aufgerufen. Dabei muss eval auf den Operator und auf jedes Argument aufgerufen werden.
      eval(add(c, 5), foo) --> apply(eval(add foo), eval(c, foo), eval(5, foo))
    6. Fehlerfall, irgendwas stimmt nicht. Dafür braucht es nun aber kein Beispiel.

apply hingegen nimmt eine Prozedur und eine Liste von Argumenten eine entgegen gibt und es auch nur drei Fälle:

    1. Die Prozedur ist primitiv und sie wird auf die Argumente angewandt.
      apply(+, 20, 5) --> 20 +5 --> 25
    2. Die Prozedur ist komplex, dann wird eval auf alle Argumente und den Methodenrumpf aufgerufen.
      apply(eval(add, foo), eval(c, foo), eval(5, foo)) -->
      apply(eval(Rumpf von add, foo), 20, 5) -->
      Hierbei wird die Umgebung von add, also foo so erweitert das 20 und 5 zu jeweils arg1 und arg2 zugewiesen werden
    3. Fehlerfall

Dieses eval und apply sind also ineinander verschränkt und rufen sich immer weiter gegenseitig auf bis der Aufruf auf elementare Operationen und Werte reduziert wurde, etwa:
add(c, 5) =
eval(apply(eval(eval(arg1 = apply(eval(arg1, foo), eval(arg2, foo))),
eval(c, foo), 5)), foo) = 25

Einfach, klar und verständlich eben.