Vagrant und Parallels

Mittlerweile nutzen wir in fast jedem Projekt Vagrant um unsere Entwicklungsumgebungen zu kontrollieren. Während unter Linux VirtualBox für die virtuellen Maschinen herhalten muss, ist es unter Mac OS X Parallels. VirtualBox würde zwar auch funktionieren, ist aber einfach nicht so performant wie Parallels.
Wenn Vagrant und Parallels bereits installiert sind, ist die Konfiguration und Benutzung von Vagrant mit Parallels ganz einfach:
Parallels Provider für Vagrant installieren:

vagrant plugin install vagrant-parallels

Beispielkonfiguration für Parallels im Vagrantfile:

config.vm.provider :parallels do |p, override|
  # Use a different image for Parallels
  override.vm.box = "parallels-box"
  # Name of the VM in Parallels
  p.name = "Blogpost"
  # Update Parallels Tools automatically
  p.update_guest_tools = true
  # Set power consumption mode to "Better Performance"
  p.optimize_power_consumption = false
  p.memory = 1024
  p.cpus = 2
end

Vagrant mit dem Provider Parallels starten:

vagrant up --provider parallels

Schönen Abend. 🙂

Eric Lippmann
Eric Lippmann
Lead Senior Developer

Eric kam während seines ersten Lehrjahres zu NETWAYS und hat seine Ausbildung bereits 2011 sehr erfolgreich abgeschlossen. Seit Beginn arbeitet er in der Softwareentwicklung und dort an den unterschiedlichen NETWAYS Open Source Lösungen, insbesondere inGraph und im Icinga Team an Icinga Web. Darüber hinaus zeichnet er für viele Kundenentwicklungen in der Finanz- und Automobilbranche verantwortlich.

Suche nach custom vars in Icinga-web

Dass viel Blut, Schweiß und Tränen in die Entwicklung von Icinga Web 2 gesteckt werden, ist ja kein Geheimnis. Aber auch Icinga-web bekommt hier und da ein bisschen Liebe: Heute wurde die neue Version v1.13.1 von Icinga-web – still und heimlich – freigegeben. Hinzugekommen ist unter anderem die Suche nach custom vars. Standardmäßig ist die Suche deaktiviert, kann aber in der module_cronks.xml im conf.d-Verzeichnis von Icinga-web aktiviert werden:



    
        
            ....
            1
            1
        
    

Viel Spaß!

Eric Lippmann
Eric Lippmann
Lead Senior Developer

Eric kam während seines ersten Lehrjahres zu NETWAYS und hat seine Ausbildung bereits 2011 sehr erfolgreich abgeschlossen. Seit Beginn arbeitet er in der Softwareentwicklung und dort an den unterschiedlichen NETWAYS Open Source Lösungen, insbesondere inGraph und im Icinga Team an Icinga Web. Darüber hinaus zeichnet er für viele Kundenentwicklungen in der Finanz- und Automobilbranche verantwortlich.

Nachgestellte Leerzeichen und String-Vergleiche in Datenbanken

Für Datenbanken die sich an den SQL-92-Standard halten, gilt für Vergleiche von character strings nach Abschnitt 8.2 Generals Rules #3, dass die zu vergleichenden Strings, vor dem Vergleich auf die selbe Länge gebracht werden müssen. Der eventuell kürzere String wird demnach nach rechts auf die Länge des zu vergleichenden Strings mit Hilfe eines pad character, meist dem Leerzeichen, aufgefüllt.
Unter character strings fallen die Typen char (character) und varchar (character varying). Diese Typen ähneln einander, werden aber auf unterschiedliche Weise gespeichert und abgerufen.
char-Werte werden beim Speichern nach rechts mit Leerzeichen bis auf die deklarierte Länge aufgefüllt, welche beim Abrufen aber wieder entfernt werden. Bei char-Werten mit einer maximalen Anzahl von vier Zeichen beispielweise, kann man deshalb nicht zwischen 'abc' und 'abc ' unterscheiden.
Im Gegensatz dazu werden varchar-Werte nur mit so vielen Zeichen wie erforderlich zuzüglich der Information über die Länge gespeichert. varchar-Werte werden beim Speichern nicht aufgefüllt. Somit werden auch Leerzeichen beim Speichern und Abrufen beibehalten.
Und jetzt? Jetzt wollen wir versuchen aus den varchar-Werten 'abc' und 'abc ' nur 'abc ' zu selektieren.
Als Erstes brauchen wir natürlich eine Datenbank mit den gewünschten Daten (hier in MySQL):

CREATE DATABASE playground;
USE playground;
CREATE TABLE pad (string varchar(5));
INSERT INTO pad VALUES('abc');
INSERT INTO pad VALUES('abc ');
INSERT INTO pad VALUES('abc  ');

Als Nächstes überprüfen wir, ob – wie im Standard definiert – bei varchar-Werten Leerzeichen beim Speichern und Abrufen beibehalten werden:

SET sql_mode = PIPES_AS_CONCAT;
SELECT '"' || string || '"', LENGTH(string) FROM pad;
+----------------------+----------------+
| '"' || string || '"' | LENGTH(string) |
+----------------------+----------------+
| "abc"                |              3 |
| "abc "               |              4 |
| "abc  "              |              5 |
+----------------------+----------------+

Das sieht doch gut aus. Nun zurück zur eigentlichen Aufgabe: Wir wollen aus diesen Daten nur 'abc ' selektieren:

SELECT '"' || string || '"', LENGTH(string) FROM pad WHERE string = 'abc ';
+----------------------+----------------+
| '"' || string || '"' | LENGTH(string) |
+----------------------+----------------+
| "abc"                |              3 |
| "abc "               |              4 |
| "abc  "              |              5 |
+----------------------+----------------+

Irgendwie nicht richtig. Oder doch? Wie eingangs erwähnt, tritt hier die Regel für Vergleiche von character strings aus dem SQL-92-Standard in Kraft: Der kürzere zu vergleichende String wird nach rechts mit Leerzeichen aufgefüllt. Wenn 'abc' mit 'abc ' verglichen wird, wird eigentlich 'abc ' mit 'abc ' verglichen, oder 'abc' mit 'abc' – wer weiß das schon so genau :).
Kommt man trotzdem auf das gewünschte Ergebnis? Klar, mit einem Zaubertrick:

SELECT '"' || string || '"', LENGTH(string) FROM pad WHERE BINARY string = 'abc ';
+----------------------+----------------+
| '"' || string || '"' | LENGTH(string) |
+----------------------+----------------+
| "abc "               |              4 |
+----------------------+----------------+

Gibt’s Ausnahmen? Ja! Bei PostgreSQL sind bei Vergleichen von varchar-Werten nachgestellte Leerzeichen signifikant.

Eric Lippmann
Eric Lippmann
Lead Senior Developer

Eric kam während seines ersten Lehrjahres zu NETWAYS und hat seine Ausbildung bereits 2011 sehr erfolgreich abgeschlossen. Seit Beginn arbeitet er in der Softwareentwicklung und dort an den unterschiedlichen NETWAYS Open Source Lösungen, insbesondere inGraph und im Icinga Team an Icinga Web. Darüber hinaus zeichnet er für viele Kundenentwicklungen in der Finanz- und Automobilbranche verantwortlich.

PHP SPL: Peek Ahead During Iteration

Eines der “Glanzstücke” von PHP und definitiv eine Blog-Serie wert, ist die seit Version 5.0.0 verfügbare SPL.
Was ist das?
SPL ist die Standard PHP Library, die laut dem PHP-Handbuch eine Sammlung von Interfacen und Klassen für die Lösung von Standardproblemen ist. Wer Klassen und Interfaces aus der SPL verwendet, die quasi eine API zu den intern eingebauten PHP Funktionen sind, kann mit Standardmitteln voll objektorientierten Code schreiben.
Nachfolgend das erste Beispiel dieser Serie.
Peek ahead during iteration

getInnerIterator()->valid() ?
        $cachingIterator->getInnerIterator()->current() : 'eoi') . PHP_EOL;
}
Eric Lippmann
Eric Lippmann
Lead Senior Developer

Eric kam während seines ersten Lehrjahres zu NETWAYS und hat seine Ausbildung bereits 2011 sehr erfolgreich abgeschlossen. Seit Beginn arbeitet er in der Softwareentwicklung und dort an den unterschiedlichen NETWAYS Open Source Lösungen, insbesondere inGraph und im Icinga Team an Icinga Web. Darüber hinaus zeichnet er für viele Kundenentwicklungen in der Finanz- und Automobilbranche verantwortlich.

Graphite auf CentOS, RHEL oder Fedora installieren

Um Graphite auf einem CentOS, RHEL oder Fedora zu installieren, muss das EPEL Repository eingebunden werden. Danach können die zu Graphite gehörenden Pakete installiert werden:

yum install python-whisper python-carbon graphite-web

Graphite-web benötigt noch eine Datenbank um Session- und Benutzerinformationen zu speichern, zum Beispiel MySQL:

# mysql -u root -p
mysql> CREATE DATABASE graphite;
mysql> GRANT ALL ON graphite.* TO graphite@localhost IDENTIFIED BY 'graphite';

Damit die erstellte Datenbank von Graphite-web genutzt wird, muss in der Datei /etc/graphite-web/local_settings.py folgende Konfiguration hinzugefügt werden:

DATABASES = {
  'default': {
    'NAME': 'graphite',
    'ENGINE': 'django.db.backends.mysql',
    'USER': 'graphite',
    'PASSWORD': 'graphite',
    'HOST': 'localhost',
    'PORT': '3306',
  }
}

Der Datenbank fehlt jetzt nur noch das Schema und ein administrativer Benutzer, die mit folgendem Kommando angelegt werden:

# /usr/lib/python2.6/site-packages/graphite/manage.py syncdb

Zum Abschluss muss in der Datei /usr/lib/python2.6/site-packages/graphite/settings.py nur noch der SECRET_KEY konfiguriert werden.

Eric Lippmann
Eric Lippmann
Lead Senior Developer

Eric kam während seines ersten Lehrjahres zu NETWAYS und hat seine Ausbildung bereits 2011 sehr erfolgreich abgeschlossen. Seit Beginn arbeitet er in der Softwareentwicklung und dort an den unterschiedlichen NETWAYS Open Source Lösungen, insbesondere inGraph und im Icinga Team an Icinga Web. Darüber hinaus zeichnet er für viele Kundenentwicklungen in der Finanz- und Automobilbranche verantwortlich.

git-archive – Dateien ignorieren

Über die Datei .gitattributes können in einem Git Repository Attribute auf Dateien und Pfaden gesetzt werden, die bestimmte Git Befehle beeinflussen. Wer git-archive nutzt, um Archive aus seinem Repository zu erstellen, kann über .gitattributes bestimmte Dateien aus Archiven ausschließen:

echo "example/* export-ignore" >>.gitattributes
git add .gitattributes
git commit -m "Do not export example data"

Das Attribut export-ignore bewirkt, dass alle Dateien die auf das Muster example/* passen, aus Archiven ausgeschlossen werden. export-ignore wirkt erst dann, wenn die Änderungen an .gitattributes commited wurden.
Den aktuellen Stand des Repository stellt man mit folgendem Befehl als Archiv bereit:

git archive -o latest.tgz HEAD

Andere Attribute passen zum Beispiel die Zeilenenden in Textdateien automatisch an, oder ersetzen $Id$ mit der commit id nach dem Check-in.
Zum Weiterlesen:

Eric Lippmann
Eric Lippmann
Lead Senior Developer

Eric kam während seines ersten Lehrjahres zu NETWAYS und hat seine Ausbildung bereits 2011 sehr erfolgreich abgeschlossen. Seit Beginn arbeitet er in der Softwareentwicklung und dort an den unterschiedlichen NETWAYS Open Source Lösungen, insbesondere inGraph und im Icinga Team an Icinga Web. Darüber hinaus zeichnet er für viele Kundenentwicklungen in der Finanz- und Automobilbranche verantwortlich.

schema.org – "Hey Google, das ist ein Video!"

Strukturierte Daten helfen Suchmaschinen dabei, die Informationen auf Webseiten besser zu verstehen und somit besser auszugeben. Einfach gesagt, werden Inhalte mit einem speziellen Markup-Format ausgezeichnet, um Suchmaschinen, Elementtyp und Eigenschaften verfügbar zu machen. Google zum Beispiel generiert aus dem Seiten-Markup Rich Snippets, die im Rahmen der Suchergebnisse angezeigt werden. Ein Snippet für eine Webseite mit Veranstaltungsdaten und entsprechendem Markup kann zum Beispiel so aussehen:
Rich Snippet für eine Seite mit Veranstaltungen
schema.org ist ein gemeinsames Projekt von Google, Microsoft und Yahoo! zur Schaffung eines Markup-Schemas für strukturierte Daten, das von allen gängigen Suchmaschinen unterstützt wird. Ein gemeinsames Markup-Vokabular erleichtert Webmastern, sich für ein Markup-Schema zu entscheiden, denn es müssen keine Kompromisse mehr eingegangen werden, weil bestimmte Markup-Typen nur von bestimmten Suchmaschinen unterstützt werden.
Wer seine Webseite mithilfe eines Schemas auszeichnet, verbessert die Qualität von Suchergebnissen und so die Sucherfahrung der Nutzer. Auf das Ranking aber, hat die Verwendung von Markup keinen Einfluss. Weitere Fragen beantwortet Google auf einer FAQ Seite.

Eric Lippmann
Eric Lippmann
Lead Senior Developer

Eric kam während seines ersten Lehrjahres zu NETWAYS und hat seine Ausbildung bereits 2011 sehr erfolgreich abgeschlossen. Seit Beginn arbeitet er in der Softwareentwicklung und dort an den unterschiedlichen NETWAYS Open Source Lösungen, insbesondere inGraph und im Icinga Team an Icinga Web. Darüber hinaus zeichnet er für viele Kundenentwicklungen in der Finanz- und Automobilbranche verantwortlich.

Asynchroner Webserver in Python mit gevent

Was ist gevent?
gevent ist eine Koroutinen-basierte Netzwerkbibliothek für Python basierend auf libev und greenlet.
greenlets sind leichtgewichtige Koroutinen, die im Prozess des ausführenden Programms laufen, aber nebenläufig ausgeführt werden. Im Gegensatz dazu werden beim Multitasking, Threads vom Betriebssystem geplant, die echt gleichzeitig laufen.
Parallelität vs Nebenläufigkeit
Zwei Aufgaben heißen nebenläufig, wenn sie voneinander unabhängig, in einem sich überschneidenden Zeitfenster, abgearbeitet werden. Dabei müssen diese nicht unbedingt echt gleichzeitig bearbeitet werden.
Zwei Aufgaben werden parallel bearbeitet, wenn sie unabhängig voneinander und zur gleichen Zeit ausgeführt werden.
“Benchmark”
Um die Performance von gevent zu vergleichen (Achtung nicht repräsentativ), lassen wir es gegen Twisted und wsgiref antreten. Die drei Kandidaten starten jeweils einen WSGI Server auf http://127.0.0.1:8088/ und beantworten jede Request mit “HTTP/1.0 200 OK”.
Mit dem Apache HTTP server benchmarking tool lassen wir 30 Sekunden (maximal 50 000 Requests) 1 000 Requests parallel laufen um vergleichen zu können, welche Implementation, die meisten Requests pro Sekunde beantwortet:

ab -r -c 1000 -t 30 http://127.0.0.1:8088/

Twisted

#!/usr/bin/python
from twisted.web import server
from twisted.web.wsgi import WSGIResource
from twisted.internet import reactor
def handle_request(env, start_response):
    status = '200 OK'
    output = 'The Output'
    response_headers = [('Content-Type', 'text/plain'),
                        ('Content-Length', str(len(output)))]
    start_response(status, response_headers)
    return [output]
if __name__ == '__main__':
    resource = WSGIResource(reactor, reactor.getThreadPool(), handle_request)
    reactor.listenTCP(8088, server.Site(resource))
    reactor.run()

Requests per second: 1093.40 [#/sec] (mean)
Time per request: 0.915 [ms] (mean, across all concurrent requests)

wsgiref

#!/usr/bin/python
from wsgiref.simple_server import make_server
def handle_request(env, start_response):
    status = '200 OK'
    output = 'The Output'
    response_headers = [('Content-Type', 'text/plain'),
                        ('Content-Length', str(len(output)))]
    start_response(status, response_headers)
    return [output]
if __name__ == '__main__':
    wsgiserver = make_server('', 8088, handle_request)
    wsgiserver.serve_forever()

Requests per second: 1610.80 [#/sec] (mean)
Time per request: 0.621 [ms] (mean, across all concurrent requests)

gevent

#!/usr/bin/python
from gevent.wsgi import WSGIServer
def handle_request(env, start_response):
    status = '200 OK'
    output = 'The Output'
    response_headers = [('Content-Type', 'text/plain'),
                        ('Content-Length', str(len(output)))]
    start_response(status, response_headers)
    return [output]
if __name__ == '__main__':
    WSGIServer(('', 8088), handle_request, spawn=None).serve_forever()

Requests per second: 2121.29 [#/sec] (mean)
Time per request: 0.471 [ms] (mean, across all concurrent requests)

Die Einfachheit des Benchmark lässt natürlich keine Rückschlüsse auf Applikationen in der echten Welt zu. gevent ist aber definitiv einen Blick wert, wenn es um asynchrone Socket-Programmierung geht.

Eric Lippmann
Eric Lippmann
Lead Senior Developer

Eric kam während seines ersten Lehrjahres zu NETWAYS und hat seine Ausbildung bereits 2011 sehr erfolgreich abgeschlossen. Seit Beginn arbeitet er in der Softwareentwicklung und dort an den unterschiedlichen NETWAYS Open Source Lösungen, insbesondere inGraph und im Icinga Team an Icinga Web. Darüber hinaus zeichnet er für viele Kundenentwicklungen in der Finanz- und Automobilbranche verantwortlich.

Leerzeichen und Zeilenumbrüchen and den Kragen gehen

Da die letzten Blogposts ausreichend Text zum Lesen enthalten, kommen von mir in aller Kürze und Würze sed-Befehle, um Leerzeichen und Zeilenumbrüche bevorzugt im Quelltext aufzuräumen.
Leerzeichen am Ende einer Zeile entfernen:

sed 's/\s\+$//' 

Aus mehreren Zeilenumbrüchen nur Einen machen:

sed '/^$/N;/^\n$/D' 

Zeilenumbruch, falls noch nicht vorhanden, am Ende einer Datei einfügen:

sed '$a\' 

Weitere sed-Einzeiler findet man z.B. hier.

Eric Lippmann
Eric Lippmann
Lead Senior Developer

Eric kam während seines ersten Lehrjahres zu NETWAYS und hat seine Ausbildung bereits 2011 sehr erfolgreich abgeschlossen. Seit Beginn arbeitet er in der Softwareentwicklung und dort an den unterschiedlichen NETWAYS Open Source Lösungen, insbesondere inGraph und im Icinga Team an Icinga Web. Darüber hinaus zeichnet er für viele Kundenentwicklungen in der Finanz- und Automobilbranche verantwortlich.

Vagrant vboxsf und statischer Inhalt

Apache und nginx benutzen zur Auslieferung von statischem Inhalt wie JavaScript-Dateien oder Bilder, den sendfile(2)-syscall. Der ist im VirtualBox/SharedFolders-Dateisystem (vboxsf) wohl nicht richtig implementiert, was zu merkwürdigen Verhalten beim Abruf kommt – z.B. nach Änderung einer Datei, wird diese nur noch abgeschnitten ausgeliefert. Beheben lässt sich das ganze durch folgende Direktiven:
nginx:

sendfile off;

Apache:

EnableSendfile Off

Zum Weiterlesen:

Und jetzt, auf zum B2RUN. 🙂

Eric Lippmann
Eric Lippmann
Lead Senior Developer

Eric kam während seines ersten Lehrjahres zu NETWAYS und hat seine Ausbildung bereits 2011 sehr erfolgreich abgeschlossen. Seit Beginn arbeitet er in der Softwareentwicklung und dort an den unterschiedlichen NETWAYS Open Source Lösungen, insbesondere inGraph und im Icinga Team an Icinga Web. Darüber hinaus zeichnet er für viele Kundenentwicklungen in der Finanz- und Automobilbranche verantwortlich.