Ich wollte nur [...] und dann ist das Universum explodiert.

Projects
Books
Archive
About









    Permalink
  1. Git | Workflow und Branching

    git-logo

    Man merkt bestimmt, dass mich Git im Moment sehr fasziniert. Es ist eine Mischung aus “Wow, ist das umfangreich” und “Ah Dokumentation ist alles”. Mittlerweile habe ich die verschiedensten Projekte in meinen Git-Server ausgelagert. Sogar meine Tiddlywiki hab ich aufgelöst und als Git-Repo umgesetzt.

    Ich las jedenfalls viel in www.progit.org. Progit ist übrigens auch ein sehr schönes Projekt. Es stellt eine Dokumentation für alle Sprachen über Git dar. Diese Dokumentation ist auf Github für jeden forkbar und jeder kann theoretisch daran mitwirken.

    Ich schweife schon wieder ab. In Progit findet man eine wundervolle Beschreibung wie man in Git einzelne Workflows bzw Branches verwaltet und wie man am effektivsten mit ihnen arbeitet. Angenommen ich habe bereits in einem bestehenden Projekt ca. 5 Commits und möchte aber vom Inital-commit noch einmal anfangen, um in eine andere Richtung weiterzuentwickeln.

                Master
                |
    o--o--o--o--o

    Sieht das ca so aus. Es besteht nun die Möglichkeit (und das ist der Grund warum ich diesen Post hier verfasse) eine neue “Entwicklungssparte” aka Branch zu starten und auf Anfang zu setzen.

    Initial     Master
    |           |
    o--o--o--o--o

    # Neuen Branch erstellen namens inital
    git branch initial

    # Branches anzeigen
    git branch -a -v
    * master                 0bfb896 removed r_error() and added some comments
    remotes/origin/HEAD    -> origin/master
    remotes/origin/initial d6600f1 First inital commit
    remotes/origin/master  0bfb896 removed r_error() and added some comments

    # Branche initial auf spezielle Commitnummer setzen
    echo "d6600f10479bb2d0d69aa8086ebe4e3149d4ef76" >> roborobo.git/.git/refs/heads/initial

    # In den neu erstellten Branch wechseln
    git checkout initial

    # Via git log kontrollieren
    git log

    # neuen Branch zum Server pushen
    git push origin initial

    Weiterhin angenommen ich entwickle in der neuen Spalte “initial” weiter und commite das wiederrum dürfte das bild so aussehen:

    Initial
       |
    o--o        Master
    |           |
    o--o--o--o--o

    <3 Git.


  2. Permalink
  3. Web | Anlaufstelle für Geekstuff? 3dsupply

    Meine Kollegen bestellen dort ja regelmäßig. Heute hab ich aber bei Christoph Grabmer (http://blog.technical-life.at/2010/04/3dsupply-unterstutzt-blogger/) von außerordentlich zuvorkommenden Aktion des 3dsupply.de-Teams gelesen. Und hab natürlich vor mitzumachen.

    Man darf sich (for free) ein Shirt aussuchen, wenn in dem eigenen Blog (der den Erwartungen entsprechen soll) ein kleiner nett gemeinter Blogpost auftaucht, der auf die Aktion hinweist. Finde ich sehr nett muss ich sagen ;) Alle Infos zur Shirt4Link Aktion hier: http://www.3dsupply.de/shirt4link/

    Aufgrund meiner Neigung zu Futurama musste es natürlich folgendes werden:

    dankend,
    Flo


  4. Permalink
  5. Git-daemon | Anti-DOS mit fail2ban

    Seit gestern versuche ich mittels Fail2ban zu vermeiden, dass mein git-daemon “geDOSt” wird. Also bei ca 10 Downloads die Klappe für die IP schliessen.
    unter:

    $ git clone git://zwetschge.org/roborobo.git

    lässt sich über den Daemon ein Repo auschecken. Der Logeintrag bei Access sieht folgendermaßen aus:

    2010-04-20_11:37:52.05907 [16810] Connection from 200.200.200.200:54283

    Nun lässt sich über ein einfaches Script, beispielsweise:

    $ for i in $(seq 1 100) ; do git clone git://zwetschge.org/roborobo.git gitrepodos$i ; done

    den Server total auslasten. Gerade bei grossen Repos wäre das fatal.
    Über RegExp und fail2ban-regexp lässt sich der Ausdruck im Logfile auch filtern und testen:

    fail2ban-regex '2010-04-20_19:52:01.41131 [26818] Connection from 200.200.200.200:54283' '.*Connection from <HOST>:.{4,5}$'

    gibt zurück der Ausdruck würde matchen. Meine Filterregel sieht auch dementsprechend aus:

    failregex = .*Connection from <HOST>:.{4,5}$

    und der Eintrag in der jail.local (damit als jail erkannt wird):

    [git-daemon]
    enabled  = true
    port     = git
    filter   = git-daemon
    logpath  = /var/log/git-daemon/current
    maxretry = 5

    ist eingerichtet. Keine Fehler im Fail2ban-Log. Alles erfolgreich gestartet. Aber der Filter matched einfach nicht wenn ich das Script ausprobiere.

    Statusabfrage des Jails:

    $ fail2ban-client status git-daemon
    
    Status for the jail: git-daemon
    |- filter
    |  |- File list:    /var/log/git-daemon/current
    |  |- Currently failed:    0
    |  `- Total failed:    0
    `- action
    |- Currently banned:    0
    |  `- IP list:
    `- Total banned:    0

    Ich weiss mir gerade nicht zu helfen. Obwohl ich das selbe Spiel mit vsftp auch gemacht habe. LINK


  6. Permalink
  7. Gitweb | URLs einbinden

    Ich habe heute längerfristig das Web durchforsten müssen, wie ich eine URL für den

    git clone git://zwetschge.org/roborobo.git

    Befehl in gitweb hinterlege. Das fand ich sehr hilfreich, denn seit ich meinen git-daemon wieder installiert habe, wäre es theoretisch möglich die PublicProjects darüber auszuchecken. Damit gitweb nun diese URL kennt, ist es nötig in dem Remote-Verzeichnis die Datei cloneurl anlegen. Kurz und prägnant damit ich es nicht wieder vergesse:

    echo "git://zwetschge.org/roborobo.git" > /home/git/public/roborobo.git/.git/cloneurl

    Dieses File liesst gitweb dann aus und schreibt die URL (in meinem Falle für roborobo) in die Summary-Übersicht mit rein.

    Beispiel: http://git.zwetschge.org/?p=roborobo.git;a=summary


  8. Permalink
  9. RegExp | Domainendungen

    Heute mal etwas weniger spektakulär. Das ist lustig, wenn ich sowas schreibe. Denn es impliziert, dass es hier schon mal etwas spektakuläres gab. Reingefallen.

    Heute wollte ein Kunde mit etwas mehr Domains wissen, welche verschiedenen TLDs genau dabei sind. Hatte auch kostentechnische Gründe. Jedenfalls wollte ich nach dem exportieren nicht wirklich die Liste durchgehen und rausschreiben.

    Wie beschreibe ich also Domains in Regular Expressions?

    ^.*\.(.*)
    Würde das Format beschreiben. Im Grunde alles was nach dem ersten Punkt einer Zeile kommt in $1 ablegen (durch () markiert). Kämen keinen doppelten Domains wie .co.uk in die Quere und Subdomains kommen nicht aus der Domainliste. Ziemlich low-level-regexp.

    cat KundenDomainliste.txt | sed -e 's/^.*\.\(.*\)/\1/'
    Gibt die komplette Domainliste (nur mit TLDs) aus. Sonderzeichen wie ( ) müssen für die Bash noch escaped werden. Desweiteren noch den Ausdruck auf den die Beschreibung zutrifft durch 1 ersetzen. Wurden aber nicht weniger Domains.

    cat KundenDomainliste.txt | sed -e 's/^.*\.\(.*\)/\1/' | uniq | sort
    Die Ausgabe von sed an uniq zu übergeben, behebt diesen Umstand. Um noch alphabetisch zu sortieren diese Ausgabe wiederrum an sort übergeben. Nett.

    Raus kommt eine Liste von Domainendungen:
    .au
    .co.uk
    .com
    .de
    .hu
    .it

    usw…
    Übrigens bin ich mir der Ironie bewusst, cat zu benutzen. Useless use of cat


  10. Permalink
  11. roborobo | selfmade robot

    Robot-icon
    Auf dem Weg durch die Filesysteme meiner Rechner/Laptops/Server kam ich immer wieder in Situationen, in denen ich gerne Files (die mir wichtig waren) an einer bestimmten Stelle aufheben wollte. Ich hab über die Monate bzw. fast schon Jahre hin immer andere Systeme, Praktiken und Plätze entwickelt in denen ich diese Configs und ähnliches ablege. Über kurz oder lang ist aber jede dieser Methoden zu aufwändig oder zu unstrukturiert. Wenn ich Konfigurationsdateien von Daemons editierte, kopierte ich vorher die alten Files an eine bestimmte Stelle. Ziemlich Standart. Der Vorgang ist an sich ziemlich mühsam. Wirr liegen irgendwo irgendwelche Files rum.

    Vor ein paar Wochen habe ich dann angefangen mir ein kleines Helferlein zu coden. Anfangs war dieses Helferlein nur für mich gedacht und demnach relativ speziell. Ich nannte ihn “roborobo”.

    Was er tut ? Ich gebe meinem Helfer einfach das File “in die Hand”. Alles andere erledigt er.

    File hinzufügen
    $ roborobo /etc/postfix/main.cf

    Alle bekannten Files updaten:
    $ roborobo

    Er nimmt das File an, ordnet es ein und sichert es in seinem Verzeichnis mit dem kompletten Verzeichnispfad nach Baumstruktur-Art. Außerdem prüft roborobo jetzt jede Stunde anhand der sha1sum ob sich in dem File seit der letzten Prüfung etwas getan hat. Falls Veränderungen da sind, wird das File mit neuem Datum wieder abgespeichert. Das sieht ungefähr so aus:

    .roborobo/
    |-- etc
    |   |-- hosts
    |   |   |-- hosts-20100409-1348
    |   |   `-- hosts-20100409-1651
    |   `-- network
    |       `-- interfaces
    |           |-- interfaces-20100409-1654
    |           `-- interfaces-20100409-1655

    Ich brauche mich somit um _nichts_ mehr kümmern. Gebe dem “kleinen” die Files die mir wichtig sind und er passt darauf auf. Fühlt sich irgendwie an wie ein Backup-Daemon ;)

    Jedenfalls, habe ich roborobo jetzt für den Einsatz auf jedem beliebigen System umgebaut und in ein Debianpaket gebastelt. Dokumentation erstellt, Config-Dateien ausreichend selbsterklärend gestaltet usw.

    Wer sich dafür interessiert oder mal testen mag:

    roborobo-Debianpaket bei Github
    roborobo-Projekt auf Github
    Alles nochmal bei meinem privaten Git-Server auf git.zwetschge.org

    Content:

    roborobo
    |-- DEBIAN
    |   `-- control
    |-- etc
    |   |-- cron.d
    |   |   `-- roborobo
    |   `-- roborobo
    |       |-- roborobo.conf
    |       `-- roborobo.path
    `-- usr
        |-- bin
        |   `-- roborobo
        `-- share
            |-- doc
            |   `-- roborobo
            |       |-- changelog
            |       `-- copyright
            `-- man
                `-- man1
                    `-- roborobo.1
    

    Das ganze wie alles was ich tue, unter GPLv3. Viel Spass damit ;)


  12. Permalink
  13. WordPress | Archive Page erstellen

    War ‘ne schwere Geburt, was sich da jetzt unter Archive versteckt. Zum einen (ungewöhnlicher Weise) schlecht und nicht umfassend genug dokumentiert bei codex.wordpress.org und zum anderen ist mein aktuelles Theme schon etwas widerspenstig was solche Sachen angeht. Unter anderem diese Widerspenstigkeit war der Punkt, warum ich kein Plugin verwenden konnte.

    Umständlich aber trotzdem zielführend. Die single.php stellt die Einzelansicht eines Blogposts. Super das will ich ja. Die Archiv-Template-Seite kann man in dem Theme-Dir ruhig liegen lassen:

    cd /var/www/blog/wp-contents/themes/clouds/
    cp single.php archive.php

    Darauf folgend habe ich die Post-Aufrufe aus dem Quelltext entfernt. Der Source ist relativ selbsterklärend. Somit besteht nur noch das Grundgerüst einer Einzelansicht. Wo sich vorher die Aufrufe für die Posts befand, fügte ich folgendes ein:

    <br/><b>Monthly outline</b>
    <?php wp_get_archives('type=monthly&show_post_count=1'); ?>
    <br/><b>Post outline by date</b>
    <?php wp_get_archives('type=postbypost');?>

    Die Funktion wp_get_archives ist allerdings sehr schön dokumentiert. Die Kunst an dem eigentlich Spass war aber das einbinden dieser archive.php-Datei.

    Damit WordPress erkennt, dass es sich bei archive.php um eine Template-Datei handelt:

    <?php
    /**
    * @package WordPress
    * @subpackage Default_Theme
    */
    /*
    Template Name: Archives
    */
    ?>

    am Anfang der Datei einfügen. Jetzt noch in WordPress die Seite erstellen. Dazu musste ich eine Seite anlegen mit leerem Inhalt. Anschliessend bei Seiten -> bearbeiten -> Quickedit(!) -> Template: Archive auswählen.


  14. Permalink
  15. Nagios | Von sprechenden Druckern, Verpflichtungen und SNMP

    Logo_Nagios

    Ich teile mir in meiner Funktion als Auszubildender mit einem Kollegen die ehrenvolle Aufgabe, ab und an den Papierstand unserer 4-Fächer Ricoh Drucker bei Gelegenheit zu “überwachen”. Im vorbeigehen sozusagen. Nun, das ganze ist ein etwas undankbarer Job – denn egal wie oft man zum Kontrollieren kommt – es kommt immer der Moment in dem nichts mehr im Fach / den Fächern ist, wenn Kollegen 200 Seiten am Stück ausdrucken.

    Um an diesem Umstand etwas zu ändern kam uns neulich eine “Notification”-Idee. In der Beschreibung des Druckers steht “SNMP-fähig”. Das Simple Network Management Protokoll bietet allerlei Möglichkeiten Informationen von Routern, Switches, Server oder Desktoprechnern abzufragen. In unserem Fall bietet auch der Drucker diese Möglichkeiten. Nach kurzer Recherche, scheint es etwas wie OIDs / MIBs für Drucker zu geben. Eine Liste dieser OIDs lässt sich mit snmpwalk ausgeben.

    snmpwalk -Os -c public -v 1 192.168.1.200

    Herauskommt eine _Menge_ an Informationen, mit der man erst mal umzugehen wissen muss. Nach etwas suchen, fiel mir folgender Block ins Auge:

    mib-2.43.8.2.1.10.1.1 = INTEGER: 55
    mib-2.43.8.2.1.10.1.2 = INTEGER: 385
    mib-2.43.8.2.1.10.1.3 = INTEGER: 55
    mib-2.43.8.2.1.10.1.4 = INTEGER: 385
    mib-2.43.8.2.1.10.1.5 = INTEGER: 0
    mib-2.43.8.2.1.11.1.1 = INTEGER: 0
    mib-2.43.8.2.1.11.1.2 = INTEGER: 0
    mib-2.43.8.2.1.11.1.3 = INTEGER: 0
    mib-2.43.8.2.1.11.1.4 = INTEGER: 0
    mib-2.43.8.2.1.11.1.5 = INTEGER: 9
    mib-2.43.8.2.1.12.1.1 = ""
    mib-2.43.8.2.1.12.1.2 = STRING: "Briefbogen"
    mib-2.43.8.2.1.12.1.3 = ""
    mib-2.43.8.2.1.12.1.4 = ""
    mib-2.43.8.2.1.12.1.5 = ""
    mib-2.43.8.2.1.13.1.1 = STRING: "Tray 1"
    mib-2.43.8.2.1.13.1.2 = STRING: "Tray 2"
    mib-2.43.8.2.1.13.1.3 = STRING: "Tray 3"
    mib-2.43.8.2.1.13.1.4 = STRING: "Tray 4"

    Kurzes systematisches Trial-and-Error am Papierfach des Druckers und Kontrolle der Veränderungen der SNMP-Ausgabe brachten mehr Aufschluss. Es schien also so als würde ein Teil der SNMP-Ausgabe die geschätzten Werte an Papier im Drucker zurückliefern.

    Genau genommen die OIDs :
    mib-2.43.8.2.1.10.1.1
    mib-2.43.8.2.1.10.1.2
    mib-2.43.8.2.1.10.1.3
    mib-2.43.8.2.1.10.1.4

    Damit lässt sich arbeiten. Für jedes Papierfach des Druckers eine OID-Nummer. snmpget lässt ein Gerät explizit nach einer OID fragen, oder ihren Descriptor.

    snmpget -v1 -Cf -c public 192.168.1.200 mib-2.43.8.2.1.10.1.1
    SNMPv2-SMI::mib-2.43.8.2.1.10.1.1 = INTEGER: 385

    Im ersten Fach sind also 385 Blätter. Schätzungsweise. So ist es also möglich den aktuellen Stand der Papierfächer abzufragen, ohne aufstehen zu müssen. Das war schonmal was. Aber wie das jetzt mit Benachrichtigung laufen lassen? CronJob? Nagios! Wo sonst httpd’s, smb-Freigaben, Erreichbarkeiten oder sonstige Dienste abgefragt und monitored werden, ließen sich auch die Papierfächer einbinden.

    Zuerst die Drucker als Hosts einbinden, die Nagios überwachen soll:

    /etc/nagios3/conf.d/host-printer1.intern.cfg
    define host {
            host_name  printer1.intern.firma.de
            alias       printer1
            address     192.168.1.200
            use         generic-host
            }

    Jetzt kennt Nagios den Host. Weiss aber weder was dort überwacht werden soll, noch mit welchem Plugin und ab welchem Schwellwert es Alarm schlagen soll. Nagios enthält ein Plugin für SNMP-Abfragen. Zu finden unter /usr/lib/nagios/plugins/check_snmp. Diesem Plugin kann ich die selben Fragen stellen wie mit snmpget. Einzige Veränderung: Schwellwerte für Warning (-w) und Critical (-c) müssen mitgegeben werden. Ich erstellte also einen sogenannten “Check”.

    /etc/nagios3/conf.d/z_check_papertray:
    define command{
             command_name    check_papertray
             command_line    /usr/lib/nagios/plugins/check_snmp -H '$HOSTADDRESS$' -C '$ARG1$' -o mib-2.43.8.2.1.10.1.$ARG2$ -w '$ARG3$': -c '$ARG4$':
    }

    Die -H Hostadresse wird aus der angegebenen Adresse im Hostfile gewonnen in dem der Check später als “Service” eingebunden wird. Außerdem noch jede Menge Argumente die auf den ersten Blick vielleicht verwirren.

    Argument1: Community für die SNMP-Anfrage. In dem Fall “public”
    Argument2: Fachnummer mit der die OID ergänzt wird.
    Argument3: Warning-Wert bei dem Nagios Alarm schlägt.
    Argument4: Critical-Wert bei dem Nagios Alarm schlägt.

    In der Hostdatei kann der definierte Check jetzt als Service eingebunden werden.

    define service {
            use                             generic-service
            host_name                      printer1.intern.firma.de
            service_description             PAPERTRAY 1 DinA4
            check_command                   check_papertray!public!1!150!56
            }

    Das ganze 4 mal. Für jedes Papierfach einmal. check_command ist dabei der ausschlaggebende Punkt. Nagios zieht aus jedem Wert nach ! seine Argumente. Community public, Fach 1, Schwellwert Warning 150 und Critical 56 oder kleiner.

    Wenn dann alles funktioniert, sieht das aus wie folgt:

    nagios

    Und im Falle eines Falles. Emails:

    ** PROBLEM Service Alert 2: printer1/PAPERTRAY 1 DinA4 is CRITICAL **

    ***** Nagios *****
    Notification Type: PROBLEM
    Service: PAPERTRAY 1 DinA4
    Host: printer1
    Address: 
    
    192.168.1.200
    
    State: CRITICAL
    Date/Time: Thu Apr 1 16:30:42 CEST 2010
    ACK by:
    Comment:
    Additional Info:
    SNMP CRITICAL - *0*

    Schön, denn wir werden jetzt immer benachrichtigt wenn kein Papier mehr im Fach ist, oder es bereits aufgefüllt wurde. Und Chef fands auch gut :)