Import old blog posts

This commit is contained in:
Martin Puppe 2020-08-08 14:30:21 +02:00
commit 8084c1e15f
23 changed files with 1384 additions and 0 deletions

View file

@ -0,0 +1,37 @@
---
layout: post
title: "Warum Octopress?"
date: 2012-02-23 11:16
comments: true
categories: Octopress
description: "Vor- und Nachteile von Octopress"
keywords: "octopress vorteile, octopress nachteile"
---
Die Auswahl an Software zum Hosten eines Weblogs ist groß. Zum einen gibt es die Spezialisten wie bspw. [Wordpress](http://wordpress.org/) oder [Serendipity](http://www.s9y.org/), zum anderen ist fast jedes der [unzähligen Content-Management-Systeme](http://en.wikipedia.org/wiki/Comparison_of_content_management_systems) mehr oder weniger gut für Blogs geeignet. Und nicht zuletzt bieten Dienste wie [Blogger](http://www.blogger.com/) und (wieder) [Wordpress](http://wordpress.com/) schlüsselfertig eine kostenlose Webpräsenz.
Ich habe mich nach einiger Überlegung für [Octopress](http://octopress.org) entschieden. Octopress ist kein Content-Management-System im eigentlichen Sinne. Man erstellt seine Blogposts lokal in einer simplen Textdatei mit einem beliebigen Editor. Die Formatierung erfolgt mittels [Markdown](http://de.wikipedia.org/wiki/Markdown). Octopress generiert aus diesen Dateien die Website. Das Ergebnis besteht fast ausschließlich aus HTML und Javascript. Und hier wird klar, was Octopress so einzigartig macht: **Es gibt keine serverseitigen Abhängigkeiten.** Datenbanksystem, PHP, Python, Ruby etc., alles nicht notwendig!
## Vorteile
Daraus ergeben sich eine Reihe interessanter Vorteile:
- *Freie Wahl der Plattform*: Da es keine Abhängigkeiten gibt, kann man ein Octopress-Blog quasi überall hosten. Ich nutze beispielsweise im Moment [Github Pages](http://pages.github.com/). Eine interessante Alternative ist sicher auch [Amazon S3](http://www.ianwootten.co.uk/2011/09/09/hosting-an-octopress-blog-on-amazon-s3). Nicht zuletzt macht das Octopress zu einer ziemlich *günstigen* Angelegenheit. Denn ein bisschen Webspace inklusive .de-Domain ist schon für unter zwei Euro monatlich zu haben.
- *Einfache Migration*: Um mit einem Octopress-Blog auf einen anderen Server zu ziehen, reicht einfaches Kopieren der Dateien.
- *Relativ einfach aufzusetzen*: Dazu verweise ich auf die [offizielle Anleitung](http://octopress.org/help/). Mit ein paar einfachen Schritten hat man schnell eine "Entwicklungsumgebung". Für die Grundkonfiguration reicht es Basis-URL, Titel, Untertitel und Autor anzugeben.
- *Einfache Bedienung*: Mit `rake new_post["title"]` wird ein neuer Post erstellt. `rake preview` erzeugt die fertige Website und startet praktischerweise gleich einen Webserver unter http://localhost:4000. Änderungen an den Quelldateien werden umgehend übernommen. Um die Änderungen schließlich ins Netz zu laden, reicht ein einfaches `rake generate && rake deploy`.
## Nachteile
Nach all dem Lob, möchte ich die Nachteile aber nicht verschweigen:
- Da ein Octopress-Blog statisch ist, ist man für eine *Kommentarfunktion* auf [Disqus](http://disqus.com/) angewiesen. Auch die *Suche* muss über einen externen Anbieter laufen.
- Vielleicht hat der Leser es bereits bemerkt: Man sollte sich schon ein wenig wohl fühlen im *Terminal*[^terminal]. Letztlich ist das Ganze aber relativ schmerzlos. Man muss eigentlich nur den Anleitungen folgen. Ist Octopress erst mal aufgesetzt, reichen für das Erstellen neuer Inhalte eine Handvoll Befehle.
- Man sollte sich jeweils eine halbe Stunde mit [Git](http://git-scm.com/) und [RVM](http://beginrescueend.com/) auseinandersetzen, um zu verstehen, was man tut.[^rvm]
- Um sein Blog komplett auf Deutsch zu übersetzen, sind noch einige [manuelle Anpassungen](http://www.uru.ch/blog/2011/09/12/octopress-oberflaeche-im-schnelldurchgang-auf-deutsch-uebersetzen/) notwendig. Hier würde ich mir wünschen, dass eine einzelne Änderung in der Konfigurationsdatei ausreicht.
[^terminal]:
Übertriebene Angst vor der Kommandozeile ist meiner Meinung nach ohnehin unbegründet.
[^rvm]:
Das kann in beiden Fällen aber ein echter Gewinn auch für andere Projekte sein.

View file

@ -0,0 +1,11 @@
---
layout: post
title: "25.02.2012: Protest gegen ACTA in Trier"
date: 2012-02-24 15:44
comments: true
categories:
keywords: "acta, trier"
---
Morgen wird auch in Trier gegen ACTA demonstriert:
[https://www.facebook.com/events/351070788257508/](https://www.facebook.com/events/351070788257508/)

View file

@ -0,0 +1,16 @@
---
layout: post
title: "Kaputte symbolische Links finden"
date: 2012-02-24 11:21
comments: true
categories: Bash
description: So lassen sich kaputte symbolische Links finden.
---
Mit folgendem Terminalbefehl lassen sich kaputte symbolische Links finden:
``` bash
find / -type l ! -exec test -r {} \; -print
```
Quelle: [http://www.linuxforums.org/forum/programming-scripting/94116-how-find-dead-symbolic-links.html#post468681](http://www.linuxforums.org/forum/programming-scripting/94116-how-find-dead-symbolic-links.html#post468681)

View file

@ -0,0 +1,22 @@
---
layout: post
title: "resumeLater 0.1 veröffentlicht"
date: 2012-03-29 11:53
comments: true
categories: resumeLater
description: resumeLater 0.1 veröffentlicht
keywords: resumelater, youtube
---
{% img right /images/posts/2012-03-29_resumeLater.svg 200 resumeLater %}
resumeLater ist eine Firefox-Erweiterung. Sie erlaubt es, die aktuelle Position in einem Youtube-Video zu speichern. Später kann die Wiedergabe an exakt der selben Stelle fortgesetzt werden. Das ist vor allem praktisch bei längeren Videos (etwa von Vorträgen), die man nicht an einem Stück schauen möchte. Download bei [addons.mozilla.org](https://addons.mozilla.org/en-US/firefox/addon/resumelater/).
In Version 0.1 wird die Video-Liste nur lokal im Browser gespeichert. Für Version 1.0 ist die Möglichkeit geplant, die Videos mit Bookmarking-Sites wie [Delicious](http://delicious.com) und [Pinboard](http://pinboard.in) zu synchronisieren. Mittelfristig ist auch eine Android-App denkbar.
Außerdem vorgesehen:
* Unterstützung weiterer Video-Seiten ([Vimeo](http://vimeo.com/), [Dailymotion](http://www.dailymotion.com/video/xpqx51) etc.)
* Deaktivieren bei Private Browsing
Quellcode und Issue-Tracker auf [Github](https://github.com/puppe/resumeLater).

View file

@ -0,0 +1,37 @@
---
layout: post
title: "XML Schema, Keys und Namespaces"
date: 2012-05-07 18:03
comments: true
categories: XML
description: "Probleme mit XML Schema, Keys und Namespaces"
keywords: "xml schema, keys, namespaces, schlüssel, namensräume"
---
Bei der Erstellung von Schemas mit einem Ziel-Namensraum kann man leicht in eine kleine, facepalm-induzierende Falle tappen, die mich heute einiges an Nerven gekostet hat. Um das Problem zu erläutern sehen wir uns am besten ein Beispiel an.
## Ohne Namensraum
{% include_code Beispielinstanz ohne Namensraum 2012-05-07/instance.xml %}
Das Dokument besteht aus einem Wurzelement `foo` und Kindelementen `bar`. Die `bar`-Elemente haben ein Attribut `id`. Nun wollen wir erzwingen, dass `id` ein Schlüssel ist. Die Instanz wäre dann nicht valide. Das entsprechende XML-Schema muss dazu etwa so aussehen:
{% include_code Schema ohne Ziel-Namensraum 2012-05-07/schema.xsd lang:xml %}
Man beachte hier vor allem die Zeilen 14 bis 16, in denen festgelegt wird, dass innerhalb des `foo`-Elements die `bar`-Elemente eindeutig durch das Schlüssel-Attribut `id` identifizierbar sein müssen.
## Mit Namensraum
Hier folgt eine Beispiel-Instanz, für die `http://foo.bar` als Namensraum festgelegt wurde.
{% include_code Beispielinstanz mit Namensraum 2012-05-07/instance_namespace.xml %}
Man könnte nun meinen, dass es ausreicht, den Namensraum entsprechend auch im Schema anzugeben. Das wurde im folgenden Beispiel in Zeile 3 und 4 getan.
{% include_code Falsches Schema mit Zielnamensraum 2012-05-07/schema_falsch.xsd lang:xml %}
Das Problem ist aber, dass die Beispiel-Instanz nicht als invalide erkannt wird, sondern klaglos akzeptiert wird. **Warum ist das so?** Das Problem ist der XPath-Ausdruck in Zeile 17. Damit werden alle `bar`-Elemente selektiert und sichergestellt, dass diese eine eindeutige `id` haben. Unser Ziel-Namensraum ist allerdings `http://foo.bar`. Das heißt wir wollen nicht `bar`-Elemente selektieren, sondern `http://foo.bar:bar`-Elemente. Das richtige Schema sieht deshalb so aus:
{% include_code Richtiges Schema mit Zielnamensraum 2012-05-07/schema_richtig.xsd lang:xml %}
Zu beachten sind die Zeilen 4 und 18. In Zeile 4 wird definiert, dass das Kürzel `foobar` für den Namensraum `http://foo.bar` steht und in Zeile 18 wird dieses Kürzel verwendet, um den *korrekten* XPath-Ausdruck zu konstruieren.

View file

@ -0,0 +1,181 @@
---
layout: post
title: "Closures in Javascript (und Scala)"
date: 2012-08-03 21:37
comments: true
categories: Javascript
keywords: "closures, javascript, scala"
---
Closures[^terminologie] sind meiner Meinung nach eines der
interessantesten Sprachkonstrukte von Javascript. Sie erlauben sehr
elegante Lösungen, die sonst nicht möglich wären. Was das konkret
bedeutet, werde ich an einem Beispiel erläutern. Zunächst möchte ich
aber erklären, was Closures sind.
## Was ist eine Closure?
**Eine Closure beinhaltet eine Funktion und (auch nicht-lokale)
Variablen, die innerhalb der Funktion referenziert werden.** Closures
verändern die Lebensdauer von Variablen. Schauen wir uns dazu ein
Beispiel an:
``` javascript
var x = 0;
function foo() {
var y = 42;
return x + y;
}
x = x + 1;
```
Wir sehen hier zwei Variablen, `x` und `y`. Im Hinblick auf die
Sichtbarkeit unterscheiden sich die Variablen darin, dass `y` nur
*innerhalb* der Funktion `foo` sichtbar ist. Was die Lebensdauer
betrifft, so existiert `y` nur während `foo` ausgeführt wird.
Sichtbarkeit und Lebensdauer für sich genommen sind keine schwierigen
Konzepte. Javascript ist allerdings eine funktionale Sprache und da wird
die Sache interessant. Javascript erlaubt es nämlich, Funktionen als
Rückgabewert anderer Funktionen zu verwenden. Dazu erweitern wir das
obige Beispiel.
``` javascript
function makeFoo() {
var x = 0;
function foo() {
var y = 41;
x = x + 1;
return x + y;
}
return foo;
}
var bar = makeFoo();
console.log(bar());
console.log(bar());
console.log(bar());
```
In der Konsole erhält man folgende Ausgabe:
```
42
43
44
```
Das ist auf den ersten Blick überraschend, wenn wir davon ausgehen, dass
lokale Variablen nur existieren, solange die Funktion, in der sie
definiert wurden, ausgeführt wird. Die Variable `x` hingegen bleibt
weiterhin innerhalb der Funktion `foo` bzw. `bar` sichtbar und behält
zudem ihren Zustand, obwohl `makeFoo` vollständig abgearbeitet wurde.
*`foo` wurde zusammen mit `x` in eine Closure gepackt*.
## Praktische Anwendung
Das obige Beispiel ist konstruiert und in der Praxis kaum nützlich.
Closures haben aber durchaus sinnvolle Anwendungen. Stellen wir uns
einmal vor, wir wollten verschiedene Objekte mit einer eindeutigen
Nummer (einer ID) versehen. Dazu wollen wir eine Funktion `generateId`
definieren, die stets eine andere Zahl zurückliefert. Der Einfachheit
halber zählen wir von 0 aufwärts. Wir haben mehrere Möglichkeiten dieses
Problem zu lösen.
### Möglichkeit 1: Globaler Zähler
``` javascript
var counter = 0;
function generateId() {
var id = counter;
counter = counter + 1;
return id;
}
var obj = {
id: generateId()
}
```
Ich halte diese Lösung für nicht sehr sinnvoll. `counter` ist eine
globale Variable. D.h. wir verschmutzen hier den globalen Namensraum mit
einer Variable, die nur für eine einzige Funktion benötigt wird.
Außerdem kann die Variable praktisch an jeder Stelle im Programm
versehentlich geändert werden. Und es wird überhaupt nicht klar, dass
counter` und `generateId` zusammengehören.
### Möglichkeit 2: Zähler und Funktion in einem Objekt
``` javascript
var idGenerator = {
counter: 0,
generateId: function() {
var id = this.counter;
this.counter = this.counter + 1;
return id;
}
};
var obj = {
id: idGenerator.generateId()
}
```
Diese Lösung ist schon etwas besser, in der Hinsicht, dass wir auf eine
globale Variable `counter` verzichten. Auch wird der Zusammenhang von
`counter` und `generateId` deutlicher. Allerdings ist diese Variante
unhandlich in der Verwendung (`idGenerator.generateId()`). Außerdem kann
auch hier `counter` an anderer Stelle im Programm geändert werden,
obwohl die Variable einzig und allein von der Funktion `generateId`
manipuliert werden sollte.
### Möglichkeit 3: Closure
``` javascript
var generateId = (function() {
var counter = 0;
return function() {
var id = counter;
counter = counter + 1;
return id;
};
})();
var obj = {
id: generateId()
}
```
Ich halte diese Lösung für die eleganteste. Der Zusammenhang von
`counter` und `generateId` wird deutlich und der Zähler ist außerhalb
der Funktion überhaupt nicht sichtbar.
## Anhang: Das Beispiel in Scala
Closures gibt es nicht nur in Javascript, sondern in wohl jeder
funktionalen Programmiersprache. Ich habe mich kürzlich im Rahmen einer
Vorlesung mit Scala beschäftigen dürfen, daher hier das obige Beispiel
in Scala:
``` scala
val generateId = (() => {
var counter = 0
() => {
var id = counter;
counter = counter + 1;
id
}
}).apply()
```
[^terminologie]:
Kurz zur Terminologie: Das deutsche Wort für „function
closure“ ist wohl „Funktionsabschluss“. Allerdings hat
man wenig Glück, wenn man danach googlet. Mir scheint der Begriff nicht
sehr gebräuchlich zu sein, also bleibe ich bei der englischen
Bezeichnung.

View file

@ -0,0 +1,234 @@
---
layout: post
title: "Hadoop unter Debian Squeeze installieren"
date: 2013-03-15 12:09
comments: true
categories: Linux
keywords: "hadoop, installation, debian"
---
Im folgenden Artikel beschreibe ich, wie Hadoop unter Debian Squeeze im
sogenannten *pseudo-verteilten* Modus installiert werden kann. Den Text
habe ich im Rahmen meiner Tätigkeit als studentische Hilfskraft beim
*Leibniz-Zentrum für Psychologische Information und Dokumentation*
([ZPID](http://www.zpid.de/)) für ein internes Wiki verfasst. Da ich
denke, dass diese Anleitung auch für andere nützlich sein könnte,
veröffentliche ich sie auch hier im Blog.
----------------------
Die wichtigsten Bestandteile von Hadoop sind:
* Hadoop Distributed File System (im Folgenden HDFS)
* Hadoop MapReduce (im Folgenden HMR)
Beide folgen einer Master/Slave-Architektur. Der Master-Dienst heißt bei
HDFS NameNode, der Slave-Dienst DataNode. Bei HMR ist der sogenannte
JobTracker der Master und die TaskTracker sind die Slaves.
Typischerweise besteht ein Hadoop-Cluster aus mindestens drei Arten von
Maschinen:
* Ein dedizierter NameNode
* Ein dedizierter JobTracker
* Mehrere Maschinen, auf denen sowohl der DataNode- als auch der
TaskTracker-Dienst läuft
Als Einstieg in den Betrieb eines Hadoop-Clusters, und um Programme zu
testen, die das HMR-Framework verwenden, bietet es sich an, erst einmal
alle Dienste auf einer einzigen Maschine laufen zu lassen. Dieser
Operationsmodus wird als *pseudo-verteilt* bezeichnet.
Wir gehen von folgenden Voraussetzungen aus:
* Betriebssystem: Debian 6 Squeeze (sollte aber auch für die meisten
anderen Debian-basierten Distributionen funktionieren)
* Installierte Java Runtime Environment 6 (hier das Paket
`openjdk-6-jre-headless`)
## Installation
Download-Links sind unter <http://hadoop.apache.org/releases.html> zu
finden. Wir laden z.B. die aktuelle stabile Version für x86-Systeme und
deren Signatur von einem Spiegel-Server herunter:
``` sh
wget http://mirror.synyx.de/apache/hadoop/common/hadoop-1.0.4/hadoop_1.0.4-1_i386.deb
wget http://mirror.synyx.de/apache/hadoop/common/hadoop-1.0.4/hadoop_1.0.4-1_i386.deb.asc
```
Außerdem laden wir die Datei KEYS von einem Server der *Apache
Foundation* und importieren die Schlüssel in den GPG-Schlüsselring.
Anschließend verifizieren wir die Signatur.
``` sh
wget http://www.eu.apache.org/dist/hadoop/common/KEYS
gpg --import KEYS
gpg --verify hadoop_1.0.4-1_i386.deb.asc
```
Schließlich installieren wir das Paket:
``` sh
sudo dpkg -i hadoop_1.0.4-1_i386.deb
```
Bei der Installation werden automatisch die Gruppe `hadoop` und die
Benutzer `hdfs` und `mapred` angelegt.
## Konfiguration
Zunächst müssen unter `/etc/hadoop` die Dateien `core-site.xml`,
`hdfs-site.xml` und `mapred-site.xml` mit folgendem Inhalt angelegt
werden:
``` xml core-site.xml
<configuration>
<property>
<name>fs.default.name</name>
<value>hdfs://localhost:9000</value>
</property>
</configuration>
```
``` xml hdfs-site.xml
<configuration>
<property>
<name>dfs.replication</name>
<value>1</value>
</property>
<property>
<name>dfs.name.dir</name>
<value>/var/local/lib/hadoop-dfs/name</value>
</property>
<property>
<name>dfs.data.dir</name>
<value>/var/local/lib/hadoop-dfs/data</value>
</property>
</configuration>
```
``` xml mapred-site.xml
<configuration>
<property>
<name>mapred.job.tracker</name>
<value>localhost:9001</value>
</property>
<property>
<name>mapred.system.dir</name>
<value>/hadoop/mapred/system</value>
</property>
<property>
<name>mapreduce.jobtracker.staging.root.dir</name>
<value>/user</value>
</property>
</configuration>
```
Eine Übersicht über alle Konfigurationsoptionen und deren Standardwerte
findet sich unter:
* `core`: <http://hadoop.apache.org/docs/r1.0.4/core-default.html>
* `hdfs`: <http://hadoop.apache.org/docs/r1.0.4/hdfs-default.html>
* `mapred`: <http://hadoop.apache.org/docs/r1.0.4/mapred-default.html>
Zuletzt müssen wir noch sicherstellen, dass die Umgebungsvariable
`JAVA_HOME` korrekt gesetzt wird. Dazu bearbeiten wir die Datei
`/etc/hadoop/hadoop-env.sh` bearbeiten. Wir ersetzen die Zeile
``` sh
export JAVA_HOME=/usr/lib/jvm/java-6-sun
```
durch
``` sh
export JAVA_HOME=/usr/lib/jvm/java-6-openjdk
```
*Wichtig!* Damit die letzte Änderung wirksam wird, müssen wir uns aus-
und wieder einloggen. Mittels `echo $JAVA_HOME` kann überprüft werden,
ob die Variable richtig gesetzt ist.
## Erstes Starten der Dienste
Wir werden zuerst das HDFS und dann HMR starten.
### HDFS starten
Bevor wir HDFS starten, müssen wir die lokalen Ordner erstellen, in
denen die Daten des HDFS abgelegt werden. Es handelt sich dabei, um die
Ordner die zuvor in der Konfigurationsdatei `hdfs-site.xml` festgelegt
wurden. Anschließend wirds verteilte Dateisystem formatiert. Einige der
Operationen müssen als Benutzer `hdfs` ausgeführt werden. In diesen
Fällen steht am Beginn des Befehls `sudo -u hdfs`.
``` sh
sudo mkdir -p /var/lib/local/hadoop-dfs
sudo chown hdfs:hadoop /var/lib/local/hadoop-dfs
sudo -u hdfs mkdir /var/lib/local/hadoop-dfs/name /var/lib/local/hadoop-dfs/data
sudo -u hdfs hadoop namenode -format
```
Nun können wir den NameNode-Dienst und den DataNode-Dienst starten.
``` sh
sudo service hadoop-namenode start
sudo service hadoop-datanode start
```
Nun sollte es möglich sein unter <http://localhost:50070> den aktuellen
Status des NameNodes und der DataNodes zu einzusehen.
Sollte irgendetwas nicht funktionieren, hilft es bei der Diagnose der
Probleme einen Blick in die Log-Dateien zu werfen. Diese werden unter
`/var/log/hadoop` abgelegt. Fehler des NameNode-Dienstes bspw. findet
man unter `/var/log/hadoop/hadoop--namenode-HOSTNAME.log`. Wobei
`HOSTNAME` durch den tatsächlichen Hostnamen bzw. Rechnernamen ersetzt
werden muss.
### HMR starten
Bevor wir die Dienste für MapReduce starten können, müssen wir im HDFS
das Verzeichnis `/hadoop/mapred/system` anlegen und `mapred` als
Besitzer des Verzeichnisses festlegen.
``` sh
sudo -u hdfs hadoop fs -mkdir /hadoop/mapred/system
sudo -u hdfs hadoop fs -chown -R mapred:hadoop /hadoop/mapred
```
Mittels `hadoop fs -ls /hadoop/mapred`, können wir uns davon überzeugen,
dass der Ordner mit den richtigen Rechten erstellt wurde.
Nun können wir die TaskTracker- und JobTracker-Dienste starten:
``` sh
sudo service hadoop-jobtracker start
sudo service hadoop-tasktracker start
```
Hat alles geklappt, lässt sich unter <http://localhost:50030> der Status
des TaskTrackers und der JobTracker einsehen.
### Benutzer-Verzeichnis erstellen
``` sh
sudo -u hdfs hadoop fs -mkdir /user/BENUTZER
sudo -u hdfs hadoop fs -chown BENUTZER:GRUPPE /user/BENUTZER
```
## Ein Beispiel-Programm ausführen
Unsere Hadoop-Installation testen wir mit einem Beispiel-Programm aus,
das in der Hadoop-Distribution enthalten ist. Zunächst kopieren wir die
Eingabedaten in das verteilte Dateisystem, dann führen wir das Programm
aus, und schließlich kopieren wir die Ausgabedaten des Programms auf das
lokale Dateisystem.
``` sh
hadoop fs -put /usr/share/hadoop/templates/conf/ input
hadoop jar /usr/share/hadoop/hadoop-examples-1.0.4.jar grep input output 'dfs[a-z.]+'
hadoop fs -get output output
```
Mittels `cat output/*` können wir uns das Ergebnis ansehen.

View file

@ -0,0 +1,41 @@
---
layout: post
title: "Unter Linux einen Proxy verwenden"
date: 2013-04-15 21:11
comments: true
categories: Linux
description: "Wie man unter Linux einen Proxy-Server verwendet, aber dennoch auf bestimmte Rechner direkt zugreift."
keywords: "linux, proxy, ausnahmen, no_proxy"
---
Manchmal ist man in Netzwerken unterwegs, deren Firewall erst mal
jeglichen Netzwerkverkehr blockt. Um den Benutzern dennoch zu
ermöglichen, zumindest auf das Web zuzugreifen, wird dann meist ein
Proxy-Server zur Verfügung gestellt, der zwischen den Benutzern und dem
eigentlichen Ziel der Anfragen vermittelt.
Nehmen wir einmal an, dass der Proxy-Server unter der IP-Adresse
192.168.0.42 erreichbar ist und auf Port 8080 lauscht. Dann muss in die
Datei `/etc/profile` folgendes eingetragen werden:
``` bash
export http_proxy=http://192.168.0.42:8080
export https_proxy=http://192.168.0.42:8080
export ftp_proxy=http://192.168.0.42:8080
export HTTP_PROXY=$http_proxy
export HTTPS_PROXY=$https_proxy
export FTP_PROXY=$ftp_proxy
```
Was aber, wenn man für manche Anfragen explizit *keinen* Proxy-Server
verwenden will, z.B. weil man auf Dienste zugreifen will, die auf dem
eigenen Rechner oder innerhalb des lokalen Netzwerkes laufen? Dazu dient
die Umgebungsvariable `no_proxy`. Möchte man beispielsweise für Anfragen
an `localhost` oder die IP-Adresse 192.168.0.10 keinen Proxy verwenden,
so sollte der Datei `/etc/profile` folgende Zeile hinzugefügt werden:
``` bash
export no_proxy=localhost,192.168.0.10
```

View file

@ -0,0 +1,36 @@
---
layout: post
title: "BitTorrent Sync auf QNAP-NAS-Geräten"
date: 2013-05-21 17:31
comments: true
categories: Linux
---
[Dropbox](http://db.tt/RfeVRSy) (Referral-Link) ist an sich eine schöne
Sache. Einfach Dateien in einen Ordner werfen, und auf jedem Gerät, das
man mit seinem Dropbox-Account verbindet, wird dieser Ordner
synchronisiert. Das erlaubt mir beispielsweise, überall auf die Dateien
zuzugreifen, die ich für die Uni brauche. Aber Dropbox hat auch
Nachteile. Es ist mit einem Dollar pro Jahr und Gigabyte recht teuer.
Außerdem hat Dropbox jederzeit Zugriff, auf die Daten, die man ihnen
anvertraut.
Und hier kommt [BitTorrent Sync](http://labs.bittorrent.com/experiments/sync.html)
ins Spiel. Das Programm erlaubt es, beliebig große Ordner zwsichen
beliebig vielen Rechnern verschlüsselt über das BitTorrent-Protokoll zu
synchronisieren. BitTorrent Sync ist zwar erst in der Alpha-Phase, läuft
aber bereits recht stabil.
Die Synchronisierung zwischen zwei Rechnern funktioniert natürlich nur,
wenn beide Rechner gleichzeitig eingeschaltet sind. Um eine mit Dropbox
vergleichbare Funktionalität zu bekommen, braucht man also einen Server,
der rund um die Uhr eingeschaltet ist, oder zumindest immer dann, wenn
einer der anderen Rechner läuft. Dafür kommt beispielsweise ein
[NAS-Server](http://de.wikipedia.org/wiki/Network_Attached_Storage) in
Frage, wie sie etwa von [QNAP](http://www.qnap.com/) hergestellt werden.
Und damit kommen wir zum eigentlichen Inhalt dieses Artikels. Ich hatte
am Pfingst-Wochenende etwas Zeit zum Experimentieren und habe BitTorrent
Sync auf meinem QNAP-NAS zum Laufen bekommen. Eine Anleitung und die
benötigten Skripte sind unter <https://github.com/puppe/btsync-qpkg> zu
finden.

View file

@ -0,0 +1,184 @@
---
layout: post
title: "Git-Repositories ohne Root-Rechte hosten mit Gitolite"
date: 2014-05-23 13:04:45 +0200
comments: true
categories: Linux
keywords: gitolite, git
---
Über die Vorzüge von [Git](http://git-scm.com/) brauche ich an dieser
Stelle nicht viele Worte verlieren. Das verteilte Versionkontrollsystem
ist bei der Software-Entwicklung ein äußerst nützliches Werkzeug. Ein
Server ist dabei nicht unbedingt notwendig, um es zu verwenden. Aber ein
zentrales Repository, das immer erreichbar ist, hat durchaus einige
Vorteile. In diesem Artikel möchte ich zeigen, wie einfach es ist, für
einzelne Benutzer oder für Gruppen Repositories auf einem Server zu
hosten. Und das Beste dabei ist: mehr als einen SSH-Zugang mit einfachen
Benutzerrechten braucht man dazu nicht!
Im Folgenden gehen wir davon aus, dass ein SSH-Zugang mit dem
Benutzernamen "benutzer" auf dem Server "server" vorhanden ist.
## Einzelne Benutzer
Möchte man ganz allein an einem Repository arbeiten, so ist die
Einrichtung besonders simpel. Es reicht aus, auf dem Server mit `git
init --bare repo.git`[^endung] ein "nacktes" Repository zu erzeugen,
also ein Repository das keine Arbeitsverzeichnis enthält. Unter der
Annahme, dass der vorhergehende Befehl im Verzeichnis $HOME/git des
Servers ausgeführt wurde, kann auf der lokalen Maschine jetzt mittels
`git clone benutzer@server:git/repo.git` ein Klon des Repositories
erstellt werden. Mit `git push` und `git pull` Änderungen zwischen
lokalem und entferntem Repository übermittelt werden.
## Gruppen
Nehmen wir nun an, dass wir auch anderen Personen lesenden oder
schreibenden Zugriff auf ein oder mehrere Repositories gewähren wollen.
Außerdem nehmen wir an, dass wir diesen Personen nur den Zugriff auf die
Repositories nicht aber auf unser komplettes Benutzerkonto gestatten
wollen. Ohne die notwendigen Rechte, um eigens dafür eine Unix-Gruppe zu
erstellen, scheint das Problem nur schwierig zu lösen zu sein. Doch dank
[gitolite](http://gitolite.com/gitolite/index.html) kann man einen
anderen Weg gehen. Neben Git muss der Server dazu nur zwei
Voraussetzungen erfüllen:
1. der Server muss SSH-Authentifizierung mittels Schlüsselpaar erlauben,
und
2. es muss ein Perl-Interpreter vorhanden sein.
Beides sollte unter den meisten Unix-Systemen gegeben sein.
Kurz zur Funktionsweise von Gitolite. SSH erlaubt die Authentifizierung
mittels
[Schlüsselpaar](https://de.wikipedia.org/wiki/Asymmetrisches_Kryptosystem).
Gitolite nutzt diesen Mechanismus, um am Schlüssel zu erkennen, welcher
Gitolite-Benutzer sich einloggt. Gitolite erlaubt dabei aber den
Benutzern nur den Zugriff auf die Git-Repositories nicht auf den
vollständigen Benutzer-Account.
### Gitolite einrichten
Als erstes erstellen wir auf dem lokalen Rechner ein SSH-Schlüsselpaar.
Dazu wird das Kommando `ssh-keygen` verwendet. Die Voreinstellung für
den Dateinamen kann man mit Return bestätigen. Es ist ratsam eine gute
Passphrase zu verwenden[^pass]. Den öffentlichen Teil des soeben
erzeugten Schlüsselpaares kopiert man nun auf den Server. Der Name der
Datei auf dem Server kann dabei frei gewählt werden, und entspricht dem
Namen unter dem Gitolite den Benutzer später kennen wird (hier:
"alice").
``` bash
scp $HOME/.ssh/id_rsa.pub benutzer@server:alice.pub
```
Nun loggen wir uns auf dem Server ein und stellen mittels `echo $PATH`
sicher, dass der Ordner `bin` im Homeverzeichnis existiert und Teil des
Suchpfads für ausführbare Dateien ist. Falls nicht:
``` bash
mkdir $HOME/bin
export PATH=$HOME/bin:$PATH
```
Damit die Änderung von `$PATH` auch nach dem Schließen des Terminals
oder dem Ausloggen erhalten bleibt, trägt man die zweite Zeile außerdem
in die Datei `$HOME/.profile` oder `$HOME/.bashrc` ein.
Nun wird Gitolite installiert und initialisiert. Hier im Beispiel wird
Gitolite in das Verzeichnis `$HOME/src/gitolite` installiert.
``` bash
mkdir $HOME/src
cd $HOME/src
git clone git://github.com/sitaramc/gitolite
gitolite/install -ln
cd $HOME
gitolite setup -pk alice.pub
```
Falls vorher schon der selbe SSH-Schlüssel zur Anmeldung verwendet
wurden, wird nach der Eingabe des letzten Befehls eventuell eine Warnung
angezeigt. Der Grund ist, dass der Schlüssel nun doppelt in der Datei
`$HOME/.ssh/authorized_keys` vorhanden ist. Falls dies der Fall ist,
sollte der entsprechende alte Eintrag entfernt werden. **ACHTUNG**: Mit
dem Schlüssel ist dann aber keine Anmeldung mehr mit vollem
Shell-Zugriff möglich, es sei denn der folgende Schritt wird ausgeführt.
### Einem Gitolite-Nutzer Shell-Zugriff erlauben
Dem Gitolite-Nutzer (hier "alice") dem der eigentliche SSH-Zugang
gehört, sollte man vollen Zugriff auf den (Unix-)Nutzeraccount gewähren.
Dazu wird zunächst der Befehl `echo alice
> $HOME/.gitolite.shell-users` ausgeführt. Dann wird an zwei Stellen die
Datei `$HOME/.gitoliterc` bearbeitet. Die erste Stelle ist die folgende
Zeile:
``` perl
# SHELL_USERS_LIST => "$ENV{HOME}/.gitolite.shell-users",
```
Hier wird das Zeichen # entfernt. Die zweite Stelle sieht so aus:
``` perl
# give some users direct shell access
# 'Shell',
```
Auch hier wird in der zweiten Zeile das # entfernt. Anschließend muss
noch der Befehl `gitolite compile; gitolite trigger POST_COMPILE`
ausgeführt werden.
### Administration von Gitolite
Damit ist die Einrichtung von Gitolite abgeschlossen. Nun stellt sich
die Frage, wie man weitere Benuter und Repositories hinzufügt. In
Gitolite wird die gesamte Administration über ein dafür bei der
Initialisierung erzeugtes Repository abgewickelt. Auf dem lokalen
Rechner wird dieses daher erst mal geklont:
``` bash
git clone benutzer@server:gitolite-admin.git
```
In diesem Repository befinden sich zwei Unterverzeichnisse, `conf` und
`keydir`. Benutzer kann man nun einfach hinzufügen, indem man deren
öffentliche Schlüssel nach `keydir` kopiert und sie nach dem Schema
`name.pub` benennt.
Um Repositories hinzuzufügen muss die Datei `conf/gitolite.conf`
bearbeitet werden. Ein Beispieleintrag sähe folgendermaßen aus:
``` text gitolite-admin/conf/gitolite.conf
repo foo
RW+ = alice
R = bob
RW = eve
```
In diesem Beispiel hat Alice darf lesen, schreiben und Rewinds
durchführen; Bob darf nur lesen; Eve darf lesen und schreiben, aber
keine Rewinds durchführen.
Nachdem Änderungen durchgeführt wurden, müssen diese committet werden und
auf den Server gepusht werden. Erst dann werden sie wirksam und hier im
Beispiel wird das Repository foo erstellt. Anschließend kann etwa Eve
mit
``` bash
git clone benutzer@server:foo.git
```
das Repository klonen. Wobei der Unix-Benuter "benutzer" für alle
Gitolite-Benutzer der selbe ist.
[^endung]:
Die Endung ".git" ist dabei nicht notwendig, aber per Konvention
werden so nackte Repositories kenntlich gemacht, um sie von normalen
Repositories zu unterscheiden.
[^pass]:
Eine gute Methode, um sichere Passphrasen zu erzeugen, die dennoch
leicht zu merken sind, ist
[Diceware](http://world.std.com/~reinhold/diceware.html).

View file

@ -0,0 +1,97 @@
---
layout: post
title: "Installing Rust nightly builds into your home directory"
date: 2014-11-26 23:53:52 +0100
comments: true
categories: Rust
description: "How to install Rust into your home directory"
keywords: "rust, rust lang, home directory, sudo, root"
---
Currently, the easiest way to get up and running with
[Rust](http://www.rust-lang.org/) is to run the following command in
your shell:
curl -s https://static.rust-lang.org/rustup.sh | sudo sh
This will install Rust into `/usr/local` and you usually need root
permissions to do that. I had been looking for an alternative for two
reasons:
* On my Macbook, `/usr/local` is mostly managed by
[Homebrew](http://brew.sh/) and `brew doctor` complains if it finds
libraries that were put there by someone else.
* I don't have root permissions at the university computer lab.
Fortunately, installing Rust into `$HOME` is relatively painless.
`rustup.sh` lets you specify a custom prefix. The above command only has
to be slightly tweaked:
curl -s https://static.rust-lang.org/rustup.sh | sh -s -- --prefix=$HOME/.local
Once Rust has been installed, there's still three things left to do.
1. Put `rustc` etc. on your $PATH.
2. Tell `rustc` where to find the Rust libraries.
3. Tell `man` where to find the manual pages.
The first two points can be accomplished by adding the following to your
`$HOME/.bashrc` or `$HOME/.zshrc`:
``` bash
if [ -d $HOME/".local/bin" ] ; then
export PATH="$HOME/.local/bin:$PATH"
fi
rust_dyld=$HOME/.local/lib/rustlib/x86_64-apple-darwin/lib
if [ ! -d $rust_dyld ] ;
rust_dyld=$HOME/.local/lib/rustlib/x86_64-unknown-linux-gnu/lib
fi
if [ -d $rust_dyld ] ; then
if [ -z $DYLD_LIBRARY_PATH ] ; then
export DYLD_LIBRARY_PATH=$rust_dyld
else
export DYLD_LIBRARY_PATH=$rust_dyld:$DYLD_LIBRARY_PATH
fi
fi
unset rust_dyld
```
Note: Take a look at lines 5 to 8. You should check whether either of
these two directories actually exists. If not, you have to modify those
lines accordingly.
If you are using [fish](http://fishshell.com/), put this into
`$HOME/.config/fish/config.fish` instead:
``` plain
if test -d $HOME/.local/bin
set -gx PATH $HOME/.local/bin $PATH
end
set -l rust_dyld $HOME/.local/lib/rustlib/x86_64-apple-darwin/lib
if test ! -d $rust_dyld
set rust_dyld $HOME/.local/lib/rustlib/x86_64-unknown-linux-gnu/lib
end
if test -d $rust_dyld
set -gx DYLD_LIBRARY_PATH $rust_dyld $DYLD_LIBRARY_PATH
end
```
Now we need to tell `man` where to find the manual pages. Add the
following line to `$HOME/.manpath`:
MANPATH_MAP /Users/martin/.local/bin /Users/martin/.local/share/man
Finally, start a new terminal session and try the following:
rustc --version
man rustc
If you later want to upgrade to the latest nightly, just rerun
`rustup.sh` (like above):
curl -s https://static.rust-lang.org/rustup.sh | sh -s -- --prefix=$HOME/.local

View file

@ -0,0 +1,53 @@
---
layout: post
title: "Fundstücke 27/2015"
date: 2015-06-28 21:20:01 +0200
comments: true
categories: Fundstücke
---
Statt gelegentlich Links kommentarlos über Twitter zu verteilen, will
ich in Zukunft hier im Blog mehr oder weniger (eher weniger) regelmäßig
auf interessante Artikel, Vorträge, Musik etc. verweisen.
[The Tradeoff Fallacy](https://www.asc.upenn.edu/sites/default/files/TradeoffFallacy_1.pdf) (PDF, via [TechCrunch](http://techcrunch.com/2015/06/06/the-online-privacy-lie-is-unraveling/))
Es wird ja gerne behauptet, dass Konsumenten gerne ihre Daten abgeben,
um im Gegenzug kostenfreie Dienste zu erhalten. Diese Studie belegt,
dass eine Mehrheit der Konsumenten keineswegs mit diesem Deal
einverstanden ist, sondern sich einfach machtlos fühlt. Meine Meinung:
Unternehmen wie Facebook sitzen dank [Netzwerkeffekt](https://de.wikipedia.org/wiki/Netzwerkeffekt) auf einem Monopol, das sie ausnutzen, um die Konditionen zu diktieren. Natürlich könnte ich auf Whatsapp verzichten und einen anderen Messenger nutzen, aber da sind eben nicht die Leute, die ich erreichen will.
[The Internet's Original Sin](http://www.theatlantic.com/technology/archive/2014/08/advertising-is-the-internets-original-sin/376041/)
Der Artikel verweist auch auf einen [großartigen Vortrag von Maciej Cegłowski](http://idlewords.com/bt14.htm). Werbefinanzierte Geschäftsmodelle führen notwendigerweise zu
Zentralisierung und Überwachung.
[A Constructive Look At TempleOS](http://www.codersnotes.com/notes/a-constructive-look-at-templeos)
Es wäre leicht, TempleOS als eine Kuriosität abzutun. Immerhin behauptet
der Programmierer, von Gott beauftragt worden zu sein, ein
Betriebssystem zu entwickeln. Aber statt billige Witze zu machen, geht
der Autor ohne Vorurteile an die Sache heran. Und er stellt fest, dass
TempleOS tatsächliche einige coole Ideen beinhaltet.
[The Death Of The Von Neumann Architecture](http://www.codersnotes.com/notes/the-death-of-the-von-neumann-architecture)
Beim Lesen des Artikels musste ich direkt an [Cory Doctorows Vortrag auf dem 28C3](http://media.ccc.de/browse/congress/2011/28c3-4848-en-the_coming_war_on_general_computation.html) denken.
Es geht um Kontrolle und Macht. Wenn ich einen Computer kaufe, gehört er
dann mir, oder dem Hersteller? [Wenn ich ein Auto kaufe, gehört es dann mir oder dem Hersteller?](http://www.slate.com/blogs/future_tense/2015/05/22/gm_and_john_deere_say_they_still_own_the_software_in_cars_customers_buy.html)
[How to Make Money from Open Source Platforms](http://www.linux.com/news/software/applications/831018-how-to-make-money-from-open-source-platforms) [Teil 2](http://www.linux.com/news/software/applications/831645-how-to-make-money-from-open-source-platforms-part-2) [Teil 3](https://www.linux.com/news/software/applications/833312-how-to-make-money-from-open-source-platforms-part-3) [Teil 4](https://www.linux.com/news/software/applications/833939-how-to-make-money-from-open-source-platforms-part-4)
Kann man mit Freier Software Geld verdienen? Vor allem Teil 3 fand ich
aufschlussreich.
[Artificial intelligence?](http://radar.oreilly.com/2015/06/artificial-intelligence.html)
"We need to be aware of our prejudices and bigotries, and make sure that we dont build systems that grant our prejudices the appearance of science. Thats ultimately why AI scares us: we worry that it will be as inhuman as humans all too frequently are. If we are aware of our own flaws, and can honestly admit and discuss them, well be OK." "We might use AI to hide from our responsibility for our mistakes, but they will most certainly be our mistakes."
[TIS-100](http://www.zachtronics.com/tis-100/) und [Door Kickers](http://inthekillhouse.com/doorkickers/)
Zwei tolle Spiele! Vielleicht muss man Programmierer sein, um mit
TIS-100 Spaß zu haben. Andererseit hätte ich selbst niemals gedacht, dass ich mal freiwillig
Assembler programmieren würde.
[9 Anti-Patterns Every Programmer Should Be Aware Of](http://sahandsaba.com/nine-anti-patterns-every-programmer-should-be-aware-of-with-examples.html)
Besonders über Punkt 3 ("Analysis Paralysis") stolpere ich leider gelegentlich.
[The World Was Never Closer To Nuclear War Than On Jan. 25, 1995](http://www.businessinsider.com/the-world-has-never-been-closer-to-nuclear-war-than-it-was-during-this-1995-event-2012-8?IR=T)
[Endangered Blood: NPR Music Tiny Desk Concert](https://www.youtube.com/watch?v=3rHD1_kUC5E)

View file

@ -0,0 +1,44 @@
---
layout: post
title: "Fundstücke 28/2015"
date: 2015-07-05 12:14:29 +0200
comments: true
categories: Fundstücke
---
## Griechenland
Die jetzige Zuspitzung der Krise in und um Griechenland ist nur ein
Symptom viel tiefer liegendender Probleme unseres Wirtschaftssystems.
Man könnte vieles zu dem Thema schreiben. Vielleicht mache ich das auch
irgendwann. Hier erst mal nur Links, ohne Kommentare.
["Die Politik hat sich ins Gefängnis der Märkte begeben"](http://www.sueddeutsche.de/politik/krise-in-griechenland-die-politik-hat-sich-ins-gefaengnis-der-maerkte-begeben-1.2538360)
[Gregor Gysi: Der Prohpet](http://le-bohemien.net/2015/07/03/gregor-gysi-der-prophet/)
["Volksbefragung": EU entsetzt über neuartige Entscheidungsmethode aus Griechenland](http://www.der-postillon.com/2015/06/volksbefragung-eu-entsetzt-uber.html)
[“Wenn es ernst wird, muss man lügen”](http://blog.zeit.de/herdentrieb/2015/07/02/wenn-es-ernst-wird-muss-man-luegen_8554)
## Sonstiges
[Inspeqtor and OSS Products With Mike Perham](http://5by5.tv/changelog/130)
Mike Perham hat zwei Open-Source-Projekte gestartet, von denen er
mittlerweile ganz gut leben kann. Genau genommen, verdient er sein Geld
mit proprietären Zusatzfeatures. [In dem Artikel](http://www.linux.com/news/software/applications/831018-how-to-make-money-from-open-source-platforms),
den ich [letzte Woche](/blog/2015/06/28/fundstucke-27-slash-2015/)
verlinkt habe, wurde dieses Modell als "Open Core" bezeichnet.
[“Kein Aserbaidschaner würde je behaupten, in einer Demokratie zu
leben”](http://erscheinungsraum.de/er033-kein-aserbaidschaner-wuerde-je-behaupten-in-einer-demokratie-zu-leben/)
Ich wusste bisher sehr wenig über Aserbaidschan. Jetzt weiß ich mehr.
[The Future of UI Design? Old-School Text Messages](http://www.wired.com/2015/06/future-ui-design-old-school-text-messages/) und [On conversational UIs](http://interconnected.org/home/2015/06/16/conversational_uis)
"Conversational UIs" sind anscheinend ein großer Trend in China. Ich bin
skeptisch. Künstliche Intelligenz ist eben meistens doch nicht
intelligent genug. Aber es schadet nicht über Alternativen
nachzudenken. Kennt jemand Beispiele für solche "Apps", die man
hierzulande mal ausprobieren könnte?
[The Lone Bellow - Button](https://www.youtube.com/watch?v=ahyIALLgUN4)

View file

@ -0,0 +1,39 @@
---
layout: post
title: "Fundstücke 31/2015"
date: 2015-08-03 17:25:43 +0200
comments: true
categories: Fundstücke
---
Nach mehrwöchiger Pause gibt es nun neue Fundstücke von mir.
[Are You Living in a Computer Simulation?](http://www.simulation-argument.com/simulation.html)
"This paper argues that at least one of the following propositions is true: (1) the human species is very likely to go extinct before reaching a “posthuman” stage; (2) any posthuman civilization is extremely unlikely to run a significant number of simulations of their evolutionary history (or variations thereof); (3) we are almost certainly living in a computer simulation. It follows that the belief that there is a significant chance that we will one day become posthumans who run ancestor-simulations is false, unless we are currently living in a simulation. A number of other consequences of this result are also discussed."
[Encryption's holy grail is getting closer, one way or another](http://www.zdnet.com/article/encryptions-holy-grail-is-getting-closer-one-way-or-another/)
"The ultimate goal -- encryption's holy grail, some have called it -- is something called fully homomorphic encryption, where the entire system works on encrypted data, and returns an encrypted result. The only point in the process where data would be decrypted would be when the user wanted to see the result, and that would presumably happen in the application or client software, not in the database server in the cloud."
[What is the Truck Factor of Popular GitHub
Applications? A First Assessment (PDF)](https://peerj.com/preprints/1233v1.pdf)
Leider hängt Software oft von einzelnen Entwicklern ab. Was passiert,
wenn diesen etwas zustößt? Bei freier Software hat man immerhin noch den
Quellcode.
[Moving Fast With High Code Quality](https://engineering.quora.com/Moving-Fast-With-High-Code-Quality)
In dem Artikel wird beschrieben, wie die Leute bei Quora für gute
Code-Qualität sorgen.
[So ein Europäer will ich gar nicht sein](http://kiezneurotiker.blogspot.de/2015/07/so-ein-europaer-will-ich-gar-nicht-sein.html)
"Das Europa 2015 ringt mir keinen Pathos mehr ab. Es steht nur noch für die Herrschaft der Buchhalter, für die Ablehnung demokratischer Instrumente wie Abstimmungen, für das Mobben legitimer Regierungen, das Europa 2015 steht für tausende ersoffene Flüchtlinge im Mittelmeer, Überwachung, Militarisierung, Freihandel zugunsten der globalisierten Konzerne, [...]" Ich selbst bin ähnlich enttäuscht von Europa.
[Einfach. Gut. Leben.](http://itsyour.life/einfach-gut-leben/)
Ich finde die Idee des Minimalismus sehr ansprechend. Mittlerweile
überlege ich mir jede Anschaffung drei mal. Zeug und Konsum machen nicht
glücklich.
[ident.me: Your Address as a Service](http://api.ident.me/)
Mit ``curl ident.me ; echo`` kann man sich ganz einfach seine
öffentliche IP-Adresse anzeigen lassen.
[Jon Spencer Blues Explosion - Get Your Pants On (Live on KEXP)](https://www.youtube.com/watch?v=i45CNVx7e8Y)

View file

@ -0,0 +1,20 @@
---
layout: post
title: "Fundstücke 32/2015"
date: 2015-08-09 21:27:24 +0200
comments: true
categories: Fundstücke
---
[Homme de Plume: What I Learned Sending My Novel Out Under a Male Name](http://jezebel.com/homme-de-plume-what-i-learned-sending-my-novel-out-und-1720637627)
"Total data: George sent out 50 queries, and had his manuscript requested
17 times. He is eight and a half times better than me at writing the
same book. Fully a third of the agents who saw his query wanted to see
more, where my numbers never did shift from one in 25."
[Beyond PEP 8 -- Best practices for beautiful intelligible code - PyCon 2015](https://www.youtube.com/watch?v=wf-BqAjZb8M)
Aufschlussreicher Vortrag, der aufzeigt wie man besser verständlichen
Python-Code schreiben kann. Die ersten ca. 20 Minuten hätte man zwar
durchaus etwas kürzen können, aber danach wird es richtig interessant.
[Deap Vally - Baby I Call Hell](https://www.youtube.com/watch?v=wUXVi3l-GUg)

View file

@ -0,0 +1,37 @@
---
layout: post
title: "Fundstücke 33/2015"
date: 2015-08-17 22:23:48 +0200
comments: true
categories: Fundstücke
---
[With Windows 10, Microsoft sells you out](http://jasonlefkowitz.net/2015/07/with-windows-10-microsoft-sells-you-out/)
"[...] **your interest in how your computer works and Microsofts interest are no
longer aligned.** While you will want your computer to do things quickly
and efficiently and unobtrusively, Microsoft will want it to do those
things slowly and clunkily and painfully; because every delay, every
useless dialog box you have to click through, is another opportunity for
them to show you an ad. And while you will want your computer to keep
your secrets secret, you wont be able to trust Microsoft to want the
same thing anymore, because suddenly all those secrets are worth money
to them. They can use them to match you up even more exquisitely with
advertisers, who have become Microsofts real customers for Windows."
[Fix Windows 10](https://fix10.isleaked.com/)
Immerhin erlaubt Windows 10 recht genau einzustellen, welche Daten an
Microsoft gesendet werden. Hier wird das ausführlich mit Screenshots
erklärt.
[Documentation at scale: The principles](http://250bpm.com/blog:58)
"1. Acknowledge that brute force doesn't work. 2. Make documentation a first
class citizen. 3. Make documentation executable. 4. Track the intent. 5. Measure it."
[Ein Abgrund von Landesverrat](http://www.zeit.de/gesellschaft/zeitgeschehen/2015-08/pressefreiheit-netzpolitik-fischer-im-recht/komplettansicht)
Bundesrichter Thomas Fischer schreibt in seiner Kolumne über den Fall
#landesverrat. Dabei kommt seine Meinung sehr deutlich durch. Auch wenn
man diese nicht vollständig teilt, ist der Artikel sehr interessant zu
lesen.
[Lee Fields and the Expressions - "Faithful Man" (Live at WFUV)](https://www.youtube.com/watch?v=4ZibJKnW6gI)

View file

@ -0,0 +1,34 @@
---
layout: post
title: "Fundstücke 34/2015"
date: 2015-08-25 17:05:05 +0200
comments: true
categories: Fundstücke
---
[Reportage: Drei Brüder aus Syrien in der Trierer Aufnahmeeinrichtung für Asylbegehrende](http://lokalo.de/artikel/95112/reportage-drei-brueder)
Ich finde den Artikel aus zwei Gründen bemerkenswert: die Reportage ist
ein positives Beispiel für Lokaljournalismus, und hier wird *mit*
Flüchtlingen statt nur *über* sie gesprochen.
[The Architecture of Open Source Applications: ZeroMQ](http://www.aosabook.org/en/zeromq.html)
Dieses Kapitel aus [The Architecture of Open Source Applications](http://aosabook.org)
gibt einen guten Überblick über [ZeroMQ](http://zeromq.org/). Das war
für mich ganz hilfreich, weil ich ZeroMQ eventuell bald für ein Projekt
einsetzen werde. Übrigens kann ich [die ganze Reihe](http://www.aosabook.org/)
empfehlen. Ich habe zwar bisher nur einzelne Kapitel gelesen, die waren
aber allesamt sehr lehrreich.
[Waterboarding für den gemeingefährlichen Irren! Deutsche Journalisten über Claus Weselsky](http://www.stefan-niggemeier.de/blog/21153/waterboarding-fuer-den-gemeingefaehrlichen-irren-deutsche-journalisten-ueber-claus-weselsky/)
Erschreckend.
[Web Design: The First 100 Years](http://idlewords.com/talks/web_design_first_100_years.htm)
"The Internet is full of projects big and small whose defining trait is
that they came out of nowhere and captured people's imaginations. It's
also full of awesome cat videos. The key part of this vision is that the
Internet succeeds by remaining open and participatory. No one acts as
gatekeeper, and it is not just a channel for mindless consumption."
([Weitere Vorträge von Maciej Cegłowski](http://idlewords.com/talks/))
[Confronting New Madrid](http://idlewords.com/2015/07/confronting_new_madrid.htm)
Maciej Cegłowski ist durch die [New Madrid Seismic Zone](https://en.wikipedia.org/wiki/New_Madrid_Seismic_Zone) gereist und schreibt darüber.

View file

@ -0,0 +1,24 @@
---
layout: post
title: "Fundstücke 35/2015"
date: 2015-08-31 12:21:17 +0200
comments: true
categories: Fundstücke
---
[Momo](https://de.wikipedia.org/wiki/Momo_%28Roman%29)
Der Roman ist 1973 erschienen, also bin ich mit meiner Empfehlung etwas
spät dran. Das Buch hat aber nichts von seiner Aktualität verloren, eher
im Gegenteil. Man findet das Werk zwar meist in der Kinder- und
Jugendbuchabteilung, aber gerade auch für Erwachsene gibt es hier viele
Denkanstöße. Was ist Zeit und wie gehen wir damit um?
[Momo, Dogen. and the Commodification of Time](http://ccbs.ntu.edu.tw/FULLTEXT/JR-MISC/101783.htm)
"This essay will explore the deep resonances between Ende's view of time
in Momo and the Buddhist perspective on time, particularly as expressed
by the Japanese Zen master Dogen (1200 - 1253). These resonances are of
more than literary or historical interest: understanding what Ende and
Dogen have to say about time gives us important insight into how we
experience time today."
[The Cat Empire Live at AB - Ancienne Belgique (Full concert)](https://www.youtube.com/watch?v=eiY3xMM4DSk)

View file

@ -0,0 +1,28 @@
---
layout: post
title: "Fundstücke 37/2015"
date: 2015-09-15 18:39:48 +0200
comments: true
categories: Fundstücke
---
[The Inspection Paradox is Everywhere](http://allendowney.blogspot.de/2015/08/the-inspection-paradox-is-everywhere.html)
Viele schöne Beispiele zu einem statistischen Paradoxon.
[“Und wenn du einfach unter einem Männernamen schreibst?”](https://zoebeck.wordpress.com/2015/08/22/und-wenn-du-einfach-unter-einem-maennernamen-schreibst/)
Die Autorin bezieht sich auf [einen Artikel](http://localhost:4000/blog/2015/08/09/fundstucke-32-slash-2015/),
den ich hier [vor ein paar Wochen](http://mpuppe.de/blog/2015/08/09/fundstucke-32-slash-2015/)
auch schon mal verlinkt hatte.
[TSA Master Keys](https://www.schneier.com/blog/archives/2015/09/tsa_master_keys.html)
Unter anderem deswegen sind staatlich vorgeschriebene Backdoors eine sehr,
sehr dumme Idee.
[The Bottom Of The Well](http://www.npr.org/sections/money/2015/07/22/425392169/episode-640-the-bottom-of-the-well)
Stellvertretend für viele spannende Episoden des Podcasts "Planet Money".
[WR470 Nachgefragt: Kurdistan](http://www.wrint.de/2015/08/30/wr470-nachgefragt-kurdistan/)
Holger Klein spricht mit Enno Lenze über dessen jüngste Reise nach
Kurdistan.
[Caravan](https://www.youtube.com/watch?v=TS-G4UQTfUo)

View file

@ -0,0 +1,18 @@
---
layout: post
title: "Fundstücke 38/2015"
date: 2015-09-20 19:37:42 +0200
comments: true
categories: Fundstücke
---
[Why Futurism Has a Cultural Blindspot](http://nautil.us/issue/28/2050/why-futurism-has-a-cultural-blindspot)
'“Futurology is almost always wrong,” the historian Judith Flanders suggested to me, “because it rarely takes into account behavioral changes.” And, she says, we look at the wrong things: “Transport to work, rather than the shape of work; technology itself, rather than how our behavior is changed by the very changes that technology brings.” It turns out that predicting who we will be is harder than predicting what we will be able to do.'
[Inside Amazon: Wrestling Big Ideas in a Bruising Workplace](http://www.nytimes.com/2015/08/16/technology/inside-amazon-wrestling-big-ideas-in-a-bruising-workplace.html)
Ich werde mich in Zukunft vermehrt nach Alternativen zu Amazon umsehen.
[Alternativlos, Folge 35](http://alternativlos.org/35/)
"In Alternativlos Folge 35 reden wir über Diskurs- und Debattenkultur und die Facebook-Löschdebatte."
[Aynotchesh Yererfu by The Budos Band](https://thebudosband.bandcamp.com/track/aynotchesh-yererfu)

View file

@ -0,0 +1,21 @@
---
layout: post
title: "Fundstücke 39/2015"
date: 2015-09-27 21:54:44 +0200
comments: true
categories: Fundstücke
---
[How to Write a Git Commit Message](http://chris.beams.io/posts/git-commit/)
Ein paar gute Hinweise.
[What Happens Next Will Amaze You](http://idlewords.com/talks/what_happens_next_will_amaze_you.htm)
"State surveillance is driven by fear. And corporate surveillance is
driven by money. The two kinds of surveillance are as intimately
connected as tango partners. They move in lockstep, eyes rapt, searching
each other's souls. The information they collect is complementary. By
defending its own worst practices, each side enables the other.
Today I want to talk about the corporate side of this partnership."
[Zitat am Freitag: Was wirklich gegen Erkältung hilft](https://buggisch.wordpress.com/2015/09/18/zitat-am-freitag-was-wirklich-gegen-erkaeltung-hilft/)
tl;dr: Ausreichend schlafen beugt Erkältungen vor.

View file

@ -0,0 +1,26 @@
---
layout: post
title: "Fundstücke 44/2015"
date: 2015-11-02 23:04:37 +0100
comments: true
categories: Fundstücke
---
[Automatic Face Recognition and Surveillance](https://www.schneier.com/blog/archives/2015/10/automatic_face_.html)
"We need limitations on how our images can be collected without our
knowledge or consent, and on how they can be used. The technologies
aren't going away, and we can't uninvent these capabilities. But we can
ensure that they're used ethically and responsibly, and not just as a
mechanism to increase police and corporate power over us."
[Schaffen wir das?](http://www.zeit.de/gesellschaft/zeitgeschehen/2015-10/fluechtlinge-fischer-im-recht/komplettansicht)
'Die Formel "nach Maßgabe der Möglichkeiten" ist also, als
verfassungsrechtliche Formel, die Verweisung entweder auf ein
intellektuelles Nichts oder auf nichts als die politische Willkür. Und
sonst wirklich nichts!'
[Hardcore History 56 Kings of Kings](http://www.dancarlin.com/product/hardcore-history-56-kings-kings/)
Eine neue Folge von Dan Carlins "Hardcore History".
[Frazey Ford - Done](https://www.youtube.com/watch?v=PXRrySTujn8)
Neulich bei [detektor.fm](https://detektor.fm/) entdeckt.

View file

@ -0,0 +1,144 @@
---
layout: post
title: "Knobeln mit Clojure"
date: 2016-04-03 20:46:00 +0200
comments: true
---
Das [ZEITmagazin](https://de.wikipedia.org/wiki/Die_Zeit#Zeitmagazin)
enthält regelmäßig unter der Überschrift "Logelei" ein Logikrätsel.
Neulich hatte ich Ausgabe 14/2016 vor mir liegen. Der vollständige Text
ist [hier](http://www.zeit.de/2016/14/spiele-logelei-14) zu finden. Ich
fasse die wesentlichen Punkte zusammen. Gesucht wird die Kombination für
ein Zahlenschloss. Das Zahlenschoss hat sechs Ziffern. Die gesuchte Zahl
muss die folgenden Bedingungen erfüllen:
1. Die Zahl ist durch 4 teilbar.
2. Die Zahl ist rückwärts ebenfalls durch 4 teilbar.
3. Die Zahl ist durch 7 teilbar.
4. Die Zahl ist *nicht* durch 11 teilbar.
5. Die Quersumme der Zahl beträgt 32.
6. Jede Ziffer kommt in der Zahl entweder doppelt oder gar nicht vor.
Nun habe ich erst versucht das Rätsel nur mit Papier und Stift zu lösen.
Leider ist Zahlentheorie nicht meine Stärke und mein Wissen erschöpfte
sich im konkreten Fall in dem Fakt, dass es reicht die letzten beiden
Ziffern einer Zahl zu betrachten, um zu überprüfen, ob sie durch 4
teilbar ist. Also habe ich stattdessen meinen Laptop zur Hand genommen
und eine
[Clojure](https://en.wikipedia.org/wiki/Clojure)-[REPL](https://en.wikipedia.org/wiki/Read%E2%80%93eval%E2%80%93print_loop)
geöffnet. Ich habe mir die nötigen Funktionen definiert und schließlich
alles zusammengestöpselt. So war das Rätsel trotz Brute-Force-Ansatz
relativ schnell gelöst.
Heute habe ich alles noch mal ordentlich aufgeschrieben.Zusätzlich habe
ich noch ein paar Tests geschrieben. Den gesamten Quellcode habe ich
[auf Github veröffentlicht](https://github.com/puppe/zahlenschloss).
Bitte schön!
``` clojure
(ns zahlenschloss.core
(:gen-class))
(defn teilbar?
"Gibt `true` zurück, genau dann wenn `n` durch `x` teilbar ist."
[x n]
(= 0 (mod n x)))
(doseq [x [4 7 11]]
(intern *ns*
(symbol (str "teilbar" x "?"))
(partial teilbar? x)))
(defn ziffern
"Nimmt eine Zahl `n` und gibt die Folge der Ziffern der Zahl zurück."
[n]
(loop [n n
ziffern (list)]
(if (= n 0)
ziffern
(recur (int (/ n 10)) (conj ziffern (mod n 10))))))
; http://stackoverflow.com/a/5058544
(defn- exp [x n]
"Berechnet x hoch n."
(reduce * (repeat n x)))
(defn wert
"Nimmt eine Folge von Ziffern und berechnet ihren Zahlenwert."
[ziffern]
(loop [summe 0
faktor (exp 10 (dec (count ziffern)))
[ziffer & ziffern] ziffern]
(if ziffer
(recur
(+ summe (* ziffer faktor))
(/ faktor 10)
ziffern)
summe)))
(defn links-auffuellen
"Nimmt eine Folge von Ziffern und füllt sie, falls nötig, links mit
Nullen auf, sodass das Ergebnis aus mindestens sechs Ziffern besteht."
[ziffern]
(loop [laenge (count ziffern)
ziffern ziffern]
(if (>= laenge 6)
ziffern
(recur
(inc laenge)
(conj ziffern 0)))))
(defn rueckwaerts
"Nimmt eine Zahl und dreht die Folge ihrer Ziffern um. Dabei wird
angenommen, dass die Zahl mindestens sechsstellig ist. Das Ergebnis
ist daher mindestens auch sechsstellig."
[n]
(wert (reverse (links-auffuellen (ziffern n)))))
(defn quersumme
"Berechnet die Quersumme der Zahl `n`."
[n]
(apply + (ziffern n)))
(defn zaehle-ziffern
"Zählt, wie oft die einzelnen Ziffern in der Zahl `n` vorkommen. Es
wird angenommen, dass `n` mindestens sechsstellig ist."
[n]
(reduce
(fn [m ziffer]
(assoc m ziffer (inc (get m ziffer 0))))
{}
(links-auffuellen (ziffern n))))
(defn doppelt-oder-gar-nicht?
"Gibt `true` zurück, genau dann wenn jede Ziffer in der Zahl doppelt
oder gar nicht vorkommt. Es wird angenommen, dass `n` mindestens
sechsstellig ist."
[n]
(if (some #(not= % 2) (vals (zaehle-ziffern n)))
false
true))
(defn -main
[& args]
(println "Mögliche Lösung(en):")
(apply
println
(->> (range 0 1000000)
; Die Zahl ist durch 4 teilbar.
(filter teilbar4?)
; Die Zahl ist rückwärts ebenfalls durch 4 teilbar.
(filter #(teilbar4? (rueckwaerts %)))
; Die Zahl ist durch 7 teilbar.
(filter teilbar7?)
; Die Zahl ist nicht durch 11 teilbar.
(filter (complement teilbar11?))
; Die Quersumme der Zahl beträgt 32.
(filter #(= 32 (quersumme %)))
; Jede Ziffer kommt entweder doppelt oder gar nicht vor.
(filter doppelt-oder-gar-nicht?)
; Wir geben maximal 10 Zahlen aus.
(take 10))))
```