Wie man den Zusammenbruch einer Zivilisation verhindert

In diesem extrem guten Vortrag geht Jonathan Blow auf die Problematik des Wissensverlustes von Zivilisationen ein. Er erklärt Anfangs das Grundproblem, warum viele alte Zivilisationen, die einst sehr mächtig und effizient waren, irgendwann einfach verschwunden sind – wie die Römer oder die Maya. In allen genannen Beispielen war es auf der einen Seite kein Untergang innerhalb eines Tages, sondern über viele Jahre, Jahrzehnte oder gar Jahrhunderte und sie hatten auf der anderen Seite vor allem eines gemeinsam: immer spielte der Verlust von Wissen die entscheidende Rolle.

Und mit diesen erkannten Prinzipien schwenkt er dann in die Neuzeit und münzt das Ganze auf die Problemantik, dass die moderne Welt nahezu komplett auf Hardware/Software basiert – was an sich ja erstmal nicht verkehrt ist. Allerdings befinden wir uns aktuell in einer Phase, in der nahezu viele Techniker zwar auf ihrem hohen Level sehr gut sind, aber die wenigsten noch die Grundlagen beherschen: wie funktioniert eine CPU bzw. wie baut man eine CPU, wie funktioniert ein Compiler im Detail, wie werden Daten im Speicher abgelegt und verwaltet und was exakt macht eine Garbage Collection? Das sind nur einzelne Bereiche, aber sie zeigen das Problem auf: je weniger Leute sich mit Basiswissen auskennen, desto höher die Wahrscheinlichkeit, dass dieses Basiswissen einmal verloren geht. Ja, natürlich kann man alles dokumentieren und archvieren. Trotzdem braucht es ja weiterhin Leute die dieses Wissen dann auch anwenden können.

Blow erklärt das sehr gut anhand der Situation in der Spielewelt (die Konferenz auf der er spricht ist eine Spielekonferenz) – genauer gesagt in der Welt der Indygames – in der es aktuell mehr oder weniger nur noch zwei führende Technologien gibt: Unity und Unreal. Keiner der entsprechenden Entwickler weiß, wie man selbst eine 3D Engine baut noch wie man absolut Low-Level einen Pixel auf den Bildschirm zeichen kann. Ich habe dafür mal von dem tollen Begriff des “Glue-Developers” gelesen: also ein Entwickler, der “nur noch” Libraries/Frameworks “zusammenklebt” und damit komplexe Applikationen baut. Das ist an sich etwas tolles, weil es effizient und wahrscheinlich sehr schnell ist. Aber was passiert, wenn es zu einem Fehler in einer darunter liegenden Library kommt?

Wie repariert man diesen Fehler bzw. wie findet man ihn überhaupt noch. NodeJS bzw. NPM ist ein gutes Beispiel wie absurd diese Abstraktion von Wissen werden kann, da dort selbst einfachste Funktionen in externe Libraries ausgelagert werden. Mit fatalen Konsequenzen.

Mich hat der Vortrag auf jeden Fall inspieriert, mal wieder einen Blick auf Basics zu werfen und lieber grundlegende Dinge wie Assembler/C Programmierung anzuschauen und mein Grundwissen da etwas auszubauen statt dem nächsten neuen Tech-Trend hinterherzueifern.

Wenn der 3D Drucker auf einmal mit Licht zeichnen kann und wunderbare Videos zaubert

An dieser Stelle fehlen mir wirklich die Worte – so begeistert bin ich vom Projekt von Josh Sheldon. Er hat einen 3D Drucker so modifiziert, dass dieser in Langzeitaufnahmen mit Licht zeichnet. Und das in einem Automatisierungsgrad und einem Professionalitätslevel, der einen einfach nur sprachlos werden lässt. Aber schaut es euch selbst an:

[Quicktip] Befehl für den Reset / Restart eines ESP 12 / 32 Microcontrollers

Normalerweise kann man einen ESP8266 per Pin „Kurzschluss“ oder einfach über die entsprechende Taste auf dem Board Neustarten. Ich wollte das ganze aber per Code machen, und die Suche nach der Lösung hatte mich etwas verzweifeln lassen. Dabei ist es doch so einfach 🙂

esp_restart();

Python MySQL connector liefert in einer Endlossschleife immer das gleiche Query Ergebnis

Für ein Projekt habe ich einen Runner laufen, der in bestimmten Intervallen eine MySQL Datenbank abfragt, ob es neue Jobs für ihn zu tun gibt. Letztendlich handelt es sich einfach um eine Endlos-While-Schleife, in der immer wieder die Query ausgeführt wird.

Das Problem war aber nun: der Runner hat im aktuellen Lauf scheinbar immer nur das Ergebnis des ERSTEN Durchlaufs der Schleife aus dem Cache gelesen. Dabei handelt es sich wohl nicht um einen Fehler auf Python Seite, sondern in MySQL selbst. Die Lösung ist zwar technisch nicht gerade schön gelöst, aber sie funktioniert: man muss einfach nur die Autocommit-Funktion für die aktuelle Verbindung zum MySQL Server aktivieren. Und das geht so:

cnx = mysql.connector.connect(...)
cnx.autocommit = True

Durch dieses Setting wird dem MySQL Server ein “set autocommit=1;” übertragen, was dann dazu führt, dass der Query Cache komplett umgangen wird.

Wie lade ich in Django 1.10 ein Bild von der Festplatte per Django Command hoch?

Für den Fall, dass man ein Bild in eine Django Applikation uploaden möchte, gibt es unzählige Tutorials – kniffelig wird es dann ein bisschen, wenn man ein Bild von der Festplatte des Servers, auf dem die Applikation läuft, mittels Django Command hochladen möchte. In meinem Beispiel importiere ich Bilder per Cronjob aus einem anderen Programm. Bisher ging der Upload auch ohne Probleme, aber seit Django 1.9 oder 1.10 wurde das Sicherheitskonzept geändert – man darf keine Dateien mehr ausserhalb des Media_Path Kontextes hochladen (Suspicious File Operation. Um das Problem zu umgehen, muss man das “normale” Fileobject, welches man normalerweise dann an das Model übergeben würde, in den Django File Wrapper packen. Dazu importiert ihr diesen Wrapper wie im Beispiel unten, übergebt den realen Pfad zum Bild und, und das ist nun wichtig, übergebt per “name” Parameter einen beliebigen Dateinamen, mit dem diese Datei dann im “Upload Prozess” von Django ankommt. Nun müsst ihr das “image” Objekt einfach nur an den Image Parameter eures Models hängen, und schon klappt das Einspielen der Datei wieder. Bei mir war es tatsächlich der fehlende “name” Parameter, der mich in die Verzweiflung getrieben hat 🙂

from django.core.files import File
image = File(open("[PATH_TO_REAL_FILE]", "rb"), name="[SOME_FILE_NAME]")

[Quicktip] Wie kann ich alle installierten Python pip Packages upgraden?

Über einen kleinen Umweg kann man auf der Bash ganz einfach alle aktuell installierten pip Pakete updaten / upgraden:

pip freeze | sed -e 's/==.*//g' > upgrade.txt
pip install --upgrade -r upgrade.txt
rm upgrade.txt

Das Script lässt sich alle installierten Pakete ausgeben, entfernt das “==[Versionsnummer]” hinter dem Namen und packt diese Liste in die Datei upgrade.txt. Anschließend wird diese Datei bei einem “pip upgrade” als “requirements.txt” übergeben und mit dem upgrade Befehl ausgeführt.

[Quicktip] Jenkins baut bereits gelöschte git Branches

Besonders wenn man einen Jenkins Job nicht auf einen bestimmten Branch einschränkt wird man dieses Problem schnell bemerken: Jenkins baut in bestimmten Fällen auf Basis von git Branches, die eigentlich bereits gelöscht sind. Der Fehler tritt auf, weil Jenkins per default das lokale git Repository nicht mit dem Origin bezüglich gelöschter Branches synchronisiert. 

Dieses Problem kann man relativ einfach beheben. Dazu geht ihr in die Konfiguration des betroffenen Jenkins Job und im Bereich “Source-Code-Management“ wählt ihr im Dropdown “Additional Behaviours“ den Punkt “Prune stale remote-tracking branches“. Damit wird vor dem Pull bzw. Fetch genau dieser Sync durchgeführt. Sprich, es werden lokal alle Branches gelöscht, die im Origin nicht mehr vorhanden sind.

[Quicktip] Wie man go get und Atlasssian Stash bzw. Gitlab zusammen bringt

In meiner Tätigkeit als Jenkins Admin hat mir das Thema „go get“ und Stash viel Kopfzerbrechen bereitet. Letztendlich ist „go get“ eine Art Alias für git pull, jedoch wird da einige Magic angewendet. Im Normalfall – also mit github und auch plain git Repos funktioniert das ganze wunderbar, sobald man aber Software wie Gitlab oder Stash verwendet, wird es etwas problematisch. Zum einen ist das „.git“, welches sowohl Gitlab als auch Stash an jedes Repo hängen ein Problem, zum anderen aber auch SSH über alternative Ports.

Zum Problem der „.git“ Endung: hängt einfach ein weiteres „.git“ an euren „go get“ Command. Also:

go get git.mydomain.com/foo/bar.git.git

Etwas kniffliger ist die Verwendung eines alternativen Ports und ssh. Stash macht nämlich genau das – der ssh Port ist 7999 in der Default Config. Aber auch hierfür gibt es eine Lösung. Dazu müsst ihr die Datei „.gitconfig“ in eurem Home Folder editieren bzw. anlegen. Die Datei muss dann so aussehen:

[url "ssh://git@stash.yourdomain.com:7999/"]
insteadOf = https://stash.yourdomain.de/

Sobald ihr nun einen Checkout auf

https://stash.yourdomain.de/foo/bar.git 

macht, biegt Git diesen Request auf

ssh://git@stash.yourdomain.com:7999/foo/bar.git

um. Somit könnt ihr auf andere Ports gehen, komplett auf andere Domains umschreiben usw.

[Quicktip] Vagrant up kann die Netzwerkinterfaces nicht starten

Wenn ihr mit

vagrant up

eine virtuelle Maschine starten wollt und während des Hochfahrens die Fehlermeldung kommt, dass das Interface eth1 (oder eth2 usw.) nicht hochgefahren werden konnte, dann probiert folgendes:

  • Virtualbox öffnen
  • die laufende Vagrant Maschine im Virtualbox beenden und anschließend dort auch wieder starten, damit ihr diese direkt steuern könnt
  • anschließend mittels User „vagrant“ und Passwort „vagrant“ einloggen
  • mittels “sudo su“ zu root wechseln
  • “/etc/network/interfaces“ mit vi aufrufen und alle Zeilen löschen, die nichts mit eth0 zu tun haben. In der Regel sollte über diesen Zeilen „# VAGRANT START“ stehen
  • Anschließend noch den Ordner “/etc/udev/rules.d/70-persistent-net.rules“ mittels “rm -rf“ löschen
  • die Maschine herunterfahren und Virtualbox beenden
  • nun mittels „vagrant up“ die Maschine wieder starten, sie sollte nun erfolgreich booten
  • sollte die Provisionierung nicht starten, dann führt anschließend noch ein „vagrant provision“ durch