Skip to content

Raspberry Pi Netzwerkdurchsatz maximieren

^ v M ><
Der Raspberry Pi ist aufgrund von Preis, Ausstattung und Grösse prädestiniert für kleinere embedded-Konfigurationen im Netzwerk. Leider scheint in der Standardkonfiguration der Netzwerkdurchsatz trotz 100Mbit-Adapter nicht komplett ausgereizt zu werden. Bei meinen Tests mit NFS, Bridging-Durchsatz (mit zusätzlicher USB-Netzwerkkarte) oder ipperf bin ich auf maximal ca 50Mbit/s gekommen. Etwas dürftig. Aber dafür gibt es eine Lösung: übertakten! Die neueren Firmware-Versionen und raspi_config lassen es zu, dass der Raspberry ohne Garantieverlust übertaktet werden darf. Allerdings ist der Nachteil weiterhin, dass der Stromverbrauch steigt, auch wenn der Raspi grad nicht arbeiten muss. Auch dem kann abhilfe geschaffen werden durch dynamisches Übertakten bzw Nutzung von Powermanagement wie man es aus der x86-Welt in Notebooks und Desktops kennt. Hierfür habe ich folgende Konfiguration verwendet:

Für dynamische Taktung wird eine Untergrenze und ein Höchsttakt in der /boot/config.txt definiert. Ich war da etwas kreativ und habe den Ruhetakt etwas heruntergesetzt, ebenso RAM und die kaum genutzte GPU etwas gedrosselt:
arm_freq_min = 500
arm_freq = 900
core_freq_min = 200
core_freq = 300
gpu_freq_min=200
sdram_freq_min = 350
sdram_freq = 450
over_voltage = [-2,2]
Mehr Einstellungsmöglichkeiten und die Standardwerte zu den einzelnen Parametern gibt es bei elinux.org.

Um nun die dynamische CPU-Taktung per Powermanagement zu aktivieren, muss der entsprechende Governor geladen werden:
echo ondemand > /sys/devices/system/cpu/cpu0/cpufreq/scaling_governor
Um diese Einstellung permanent zu machen, hält man sie am Einfachsten in der Datei /etc/rc.local fest. Eine Möglichkeit, den Governor per Kernel-Parameter zu setzen, so dass der Bootprozess vom höheren Maximaltakt profitiert, konnte ich bislang nicht ausfindig machen.

Mit dieser Einstellung wird der Netzwerkdurchsatz auf 96Mbit/s gesteigert (gem ipperf), was dem theoretischen Maximum von 100Mbit/s doch schon sehr nahe kommt.

Defekte CD oder DVD mit dd einlesen

^ v M ><
Mit einem einfachen
dd if=/dev/sr0 of=outfile.iso
lässt sich ein defekter (kleine Kratzer oder perverse Abspielschutzvorkehrungen) optischer Datenträger unter Linux leider meist nicht mehr auslesen. Sobald ein I/O-Fehler auftritt, wird dd den Kopiervorgang abbrechen. Allerdings lässt sich dd anweisen, dass es Fehler ignorieren soll:
dd if=/dev/sr0 of=outfile.iso bs=2048 conv=noerror,notrunc iflag=nonblock
Mit etwas Geduld klappt es so aber meistens. "Etwas" sollte man wörtlich nehmen und sich im schlimmsten Fall den Tag reservieren.

Pulseaudio vs Netzwerkstreaming vs funktionierende Software Teil 2

^ v M ><
Leider hat sich meine letzte Anleitung nicht komplett bewährt. RTP über WLAN hat einen sehr grossen Nachteil: Das WLAN wird durch die 1.5Mbit RTP-Traffic komplett mit UDP-Paketen geflutet und überlastet. Egal was für ein Access Point mit egal welcher Firmware - die Latenzen gehen bis zur Unbenutzbarkeit hoch, sobald Musik läuft.
Mit direkter Punkt-zu-Punkt-Verbindung über Pulseaudio tritt das Problem jedoch nicht auf.

Daher habe ich eine neuere, viel einfachere Konfiguration erstellt, welche serverseitig keine Installation von Pulseaudio mehr erfordert. Etwas Hilfe von Onkel Google haben mich zu dieser Anleitung geführt, welche ich etwas vereinfacht und an meine Anforderungen angepasst habe. Eine direkte Umsetzung dieser Anleitung war in meinem Fall nicht zielführend, da der Pulseaudio-Client (bzw module-tunnel-sink) eine einmal abgebrochene Verbindung nicht wieder aufbauen kann. Es müsste serverseitig das komplette mpd/pulseaudio-Konstrukt neu gestartet werden, wenn sich der Client (Raspberry oder Desktop) kurz aus dem Netzwerk abmelden (Netzwerk-Hickup, Neustart o.ä.).

Die Lösung: mpd einfach direkt zum Sink-Server verbinden lassen.

Sink-Konfiguration (rc.local-Eintrag auf dem Raspi):
pulseaudio -D --log-target=syslog --start --realtime --load=module-native-protocol-tcp auth-anonymous=1 listen=0.0.0.0
Zu beachten ist, dass so jeder Rechner im Netzwerk Audiodaten an den Raspi streamen kann.
Sink-Konfiguration Klickibunti: papref starten und im Tab "Netzwerk-Server" die Häkchen bei "Enable network access to local sound devices" und den zwei darunter liegenden Boxen setzen.
mpd-Konfiguration:
audio_output {
type "pulse"
name "Desktop"
server "192.168.0.6"
sink "alsa_output.pci-0000_05_06.0.analog-stereo"
}
audio_output {
type "pulse"
name "Raspeakr"
server "192.168.0.11"
}


Bricht die Netzwerk-Verbindung doch mal ab, so ist spätestens nach dem nächsten Songwechsel wieder Lärm da.

Allerdings ist die Lösung auch nicht 100% perfekt, leichte Aussetzer können vorkommen.

Kaputtgeflashten WLAN-Accesspoint wiederherstellen

^ v M ><
Der WR841N v8 von TP-Link ist eigentlich gar kein schlechter Router für seinen Preis. Der Billigstheimer kommt mit ganz tauglicher Hardware daher und die Software ist eigentlich gar nicht sooo schlecht. Allerdings sind die Latenzen doch eher hoch und der Jitter untragbar. Zum Glück unterstützt die neuste Version von OpenWRT auch die neuste Revision des Geräts. Also auf, frische Firmware aufspielen. Nun gibt es zwei Images mit unterschiedlichen Dateisystemen, jffs2 und squashfs. Gemäss der Beschreibung schien mir jffs2 doch die bessere Wahl zu sein. Grosser Fehler, das jffs2-Image bootet nämlich nicht sauber, das Resultat ist ein unbrauchbarer Ziegelstein.

Was tun? Nun, man kann verzweifeln und in anbetracht des lächerlichen Preises ein Ersatzgerät bestellen oder sich vom Ehrgeiz packen lassen und den unbrick-Prozess starten. Dazu mussten als erstes die PINs in den Serial Header gelötet werden. Die Löcher sind praktischerweise schon da, aber die PINs waren wohl zu teuer. Na gut, Lötkolben her und los.

Danach wird das eigentlich für den Raspberry Pi angeschaffte serielle Konsolenkabel angesteckt. Das PIN-Layout ist identisch mit v7, nur um 90° verdreht. D.h. der alleinstehende PIN ist weiterhin TX. Entsprechend wird das Kabel nun angesteckt und mit einem PC verbunden. Da die Versorgung nun über den seriellen Port erfolgt, startet der Router auch sofort und per minicom lässt sich der Bootprozess mitverfolgen:
minicom --device /dev/ttyUSB0 -b 115200


Scheinbar hängt der Bootprozess beim laden der USB-Module (ohci_hcd). Das lässt sich verhindern, indem man in den Failsafe-Mode bootet. Dazu muss man, wenn der Prozess für ca 1s steht und die entsprechende Meldung anzeigt, rasch f[enter] eintippen. Schon erhält man eine root-Konsole und kann mit debugging loslegen.

Tatsächlich löste sich das Problem nun recht simpel. eth0 war unter 192.168.1.1 verfügbar, allerdings war eth0 der blaue WAN-Port, keiner der gelben LAN-Ports. Ausserdem schien der DHCP-Server nicht in Betrieb zu sein, so dass dem angeschlossenen Computer manuell eine IP-Adresse vergeben werden musste:
ifconfig eth0 192.168.1.2 netmask 255.255.255.0
. Anschliessend musste auf dem Router noch die Weboberfläche gestartet werden:
/etc/init.d/uhttpd start
und schon konnte bequem per Klickibunti das korrekte Firmware-Image (squashfs) aufgespielt werden.

Das Resultat: ein superflotter WLAN-Router mit relativ tiefen und stabilen Latenzen - zum Spottpreis.

Und vermutlich wäre der Lötkolben gar nicht mal nötig gewesen. Scheinbar kommt man auch in den Failsafe-Mode, indem man direkt nach dem Einschalten den Reset-Knopf drückt. Konsolenzugriff erhält man in diesem Fall per Telnet.

Pulseaudio vs Netzwerkstreaming vs funktionierende Software

^ v M ><
Wie verwandle ich einen Raspberry Pi, eine USB-WLAN-Karte und ein Paar USB-Lautsprecher in eine mobile Krachstation, welche die gleiche Musik wiedergeben kann, wie mein Hauptrechner? Nun, die Theorie wäre ja einfach: Auf dem Hauptrechner läuft mpd und dieser kann in quasi jedem gewünschten Format und Protokoll ausgeben. Dieser wird nun zwecks Steigerung der Verfügbarkeit erstmal auf den Intranet-Server gezügelt.


Der erste Versuch war, einen normalen Stream zu verwenden. Dazu wird wahlweise mpds integrierter Web/Streaming-Server gestartet (Nachteil: sobald man die wiedergabe pausiert, wird das Socket geschlossen, ein allfälliger Client wird deshalb terminiert), oder noch ein Icecast zwischengeschaltet (Vorteil: ein permanenter Stream, sobald mpd pausiert wird, strahlt Icecast ein (lautloses) Fallback-File in Endlosschleife aus). Leider hat diese Lösung einen riesigen Nachteil: Der Client hängt 2-10 Sekunden hinterher. Startet man die Wiedergabe, drückt man auf Pause oder wechselt manuell zum nächsten Lied, dauert es eine mittlere Ewigkeit, bis die Änderung beim Client ankommt. Fazit: für meinen Zweck unbrauchbar.


Na gut, zweiter Versuch. mpd Pipe-Output. Damit gibt mpd einfach einen rohen Audiostream per Pipe an ein anderes Programm weiter. Diesen Stream kann man entweder direkt per netcat übers Netzwerk raushauen oder aber, um das Netz nicht übermässig zu belasten, erst zu ogg codieren. Hierzu trägt man in der /etc/mpd.conf folgendes ein:
audio_output {
type "pipe"
name "my pipe"
command "oggenc -r -Q -q4 - | nc 192.168.0.60 8765"
}

Auf der Empfängerseite wird mittels xinetd ein passender Empfänger bereitgestellt. Dazu benötigt man einerseits eine Konfiguration für xinetd unter /etc/xinetd.d/oggplay:
service oggplay
{
port = 8765
type = UNLISTED
socket_type = stream
wait = no
user = root
server = /usr/local/bin/oggplay.sh
log_on_failure += USERID
disable = no
}

Leider scheint diese nur mit root-Rechten zu funktionieren, von xinetd aus gestartet kann ein Prozess des eingeschränkten Benutzers aus irgend einem Grund nicht auf die Soundhardware zugreifen (von einer Login-Shell aus geht das jedoch). Genauer untersucht habe ich das nicht, da ich ja erst mal einen Proof-Of-Concept wollte. Ebenfalls wird noch das eigentliche Player-Skript unter /usr/local/bin/oggplay.sh benötigt:
#!/bin/bash
/usr/bin/ogg123 -v -d wav -f- - | /usr/bin/aplay -v -D sysdefault:CARD=USB

Das funktionert soweit... nicht wirklich. Der erste Song konnte in aller Regel noch wiedergegeben, spätestens nach dem ersten Songwechsel waren dann aber massive Aussetzer in der Wiedergabe. Kein Wunder, hier wird ja auch überhaupt nichts gepuffert. Sehr traurig allerdings, dass es auch über Ethernet mit geringer Latenz/Jitter kein Bisschen besser funktioniert als über WLAN. Fazit: unbrauchbar.


Als nächstes habe ich dann zu ganz radikalen, verzweifelten Massnahmen gegriffen und im dritten Versuch angefangen, meine Systeme mit Pulseaudio zu verschandeln (und natürlich erst noch ein Diskimage gezogen). Auf dem Server werden folgende Pakete und Konfiguration benötigt:
aptitude install pulseaudio pulseaudio-utils mpd mpc

/etc/mpd.conf:
audio_output {
type "pulse"
name "Multicast RTP"
sink "rtp"
}

/etc/pulse/default.pa in Debian 6 / PA 0.9:
#! /usr/bin/pulseaudio -nF
load-module module-native-protocol-unix
load-module module-suspend-on-idle timeout=1
load-module module-null-sink sink_name=rtp description="Multicast RTP"
load-module module-rtp-send source=rtp.monitor

bzw unter Debian 7 / PA 2.0:
#! /usr/bin/pulseaudio -nF
load-module module-native-protocol-unix
load-module module-suspend-on-idle timeout=1
load-module module-null-sink sink_name=rtp sink_properties="device.description='RTP Multicast Sink'"
load-module module-rtp-send source=rtp.monitor

/etc/pulse/daemon.conf:
exit-idle-time = -1
default-sample-format = s16le

Das war's schon :-)
Nehmen wir nun den Raspberry in Angriff. Zuerst werden ein paar PulseAudio-Konfigurationswerkzeuge installiert:
aptitude install paman paprefs pavucontrol

Des weiteren wird PulseAudio so konfiguriert, dass standardmässig die USB-Lautsprecher verwendet werden. Hierzu genügt die Zeile "default-sink = 1" in der Datei /etc/pulse/client.conf.
Startet man nun die grafische Oberfläche und aktiviert dort den RTP-Empfang per Klickibunti in paprefs, haut die Sache auch sofort hin. Das ist aber witzlos, wenn die Kiste ja nachher Headless und ohne angemeldeten Benutzer funktionieren soll. Folglich beendet man X11 wieder. In den Howtos zu diesem Thema (u.a. auch in den Raspberry-spezifischen Diskussionen wie hier und hier) wird gesagt, dass "einfach nur" in /etc/pulse/default.pa die Zeile "load-module module-rtp-recv" einfügt und PulseAudio durch Änderung in /etc/default/pulseaudio als Systemdienst eingerichtet werden soll. Eventuell muss man noch in der /etc/pulse/daemon.conf "resample-method = src-sinc-fastest" eintragen. Nach einem Neustart soll es auch schon laufen. Simpel, oder? Da muss ein Haken dran sein! Ist auch so. Davon zeigt sich das System nämlich überhaupt nicht beeindruckt und bleibt mucksmäuschenstill.
Was ist nun also der Unterschied zwischen der Kommandozielen- und der GUI-Konfiguration? Keine Ahnung. Auch "pacmd dump" hilft hier nicht weiter. Wie bekommt man den Dreck trotzdem zum laufen? Nun, wie so oft mit der beliebten Methode "von hinten durch die Brust ins Auge": Die Änderung in /etc/default/pulseaudio wird wieder rückgängig gemacht, so dass Pulseaudio nicht beim Systemstart gestartet wird. Danach trägt man in die /etc/rc.local einen fixen Aufruf des PulseAudio-Dienstes ein, und zwar mit folgender Zeile:
su pi -c 'pulseaudio -D --log-target=syslog --start --realtime --resample-method=src-sinc-fastest'

und Tadaaaa! Es lärmt, sobald der mpd anfängt zu spielen. Allerdings ist "Lärm" wirklich die passende Bezeichnung. Die Wiedergabe scheppert leicht, was wohl dem Resampling geschuldet ist.

Jetzt steht mir nur noch eines bevor: Auch meinen Desktop mit Pulseaudio zu ruinieren. Dies, nachdem das aktuelle Alsa-Setup doch prächtig funktioniert.

magmakeys - Lautstärke regeln ohne angemeldet zu sein

^ v M ><
Für eine kopflose Multimediabox unter Debian (bzw Raspbian, es handelt sich hier um einen Raspberry Pi) wollte ich die Lautstärkeregelung der angeschlossenen USB-Lautsprecher nutzen. Diese Tasten senden letztendlich einfach Keyboard-Signale. Unter X11 wird das von den meisten Window Managern und Desktop Environments unterstützt. In der Konsole ist das nicht ganz trivial, insbesondere, wenn kein Benutzer angemeldet ist. Mit dem in Perl geschriebenen magamkeys gibt es aber dennoch einen Weg. Leider ist die Software wieder einmal ein Paradebeispiel perfekt lückenloser Dokumentation (denn wo gar keine Doku ist, da können auch keine Lücken sein...), so dass ich selber etwas denken musste.

Abhängigkeiten:
aptitude install git dbus hal libnet-dbus-perl alsa-utils

Danach die Software per git auf das System holen:
git clone https://github.com/wertarbyte/magmakeys.git

Nun kommt der spassige Teil. Alles installieren, ohne das System unnötig zuzumüllen. Natürlich muss man das richtige Perl-Verzeichnis erstellen, die Version ergibt sich aus dem Befehl perl --version:
mkdir -p /usr/local/lib/perl/5.14.2/
cp -r magmakeys/lib/magmakeys/ /usr/local/lib/perl/5.14.2/
mkdir -p /usr/share/magmakeys
cp magmakeys/share/eventcodes.txt /usr/share/magmakeys/
cp magmakeys/bin/magmakeys /usr/local/bin/
cp magmakeys/initscript/magmakeys /etc/init.d/
chmod +x /etc/init.d/magmakeys
mkdir -p /etc/magmakeys/keys.d/
vi /etc/magmakeys/keys.d/amixer

Nun muss noch die Konfiguration für amixer erstellt werden. Ich will die per USB angeschlossene Soundkarte steuern, welche als Card 1 erkannt wird. Die interne Soundkarte ist Card 0. Ein Hinweis auf die Konfiguration findet sich einerseits im git-Repostitory, genommen habe ich etwas, das ich bei Gentoo gefunden habe:
# volume control
KEY_VOLUMEUP 1 /usr/bin/amixer -c1 set PCM 2%+
KEY_VOLUMEDOWN 1 /usr/bin/amixer -c1 set PCM 2%-
# keep changing the volume when holding the key
KEY_VOLUMEUP 2 /usr/bin/amixer -c1 set PCM 2%+
KEY_VOLUMEDOWN 2 /usr/bin/amixer -c1 set PCM 2%-
KEY_MUTE 1 /usr/bin/amixer -c1 set PCM toggle

Nun lässt sich die Software probeweise mal starten:
magmakeys -k /etc/magmakeys/keys.d/ -t /usr/share/magmakeys/eventcodes.txt

Beim Drücken auf die Tasten an den Boxen müsste sich etwas in der Konsole tun. Wenn das erfolgreich war, kann man den Dienst permanent starten. Dazu muss aber erst das Init-Skript leicht geändert werden: Aus der Zeile "# Required-Start: $remote_fs hal" wird hal gestrichen, da dieser eh über dbus initialisiert wird und kein eigenes Startskript mehr hat. Die Zeile lautet neu also "# Required-Start: $remote_fs". Und die Zeile "DAEMON=/usr/sbin/$NAME" wird zu "DAEMON=/usr/local/bin/$NAME", da ich das Skript nach /usr/local/bin kopiert hatte. Nun kann's losgehen:
vi /etc/init.d/magmakeys
/etc/init.d/magmakeys start
update-rc.d magmakeys defaults

Gnokii und Phonet

^ v M ><
Die neueren Versionen von Gnokii (0.6.30 und neuer) bieten eine neue Verbindungsoption zu s40-Telefonen: Den Phonet-Treiber. Leider ist die Dokumentation im Gnokii-Wiki dazu sehr spärlich und auch sonst weiss das Internet nicht viel dazu. Jedoch ist er relativ gut im Source-Tarball des Gnokii-Projekts beschrieben. Die Source brauchte ich sowieso, um das aktuelle Gnokii für mein Debian Squeeze zu kompilieren.

Die Idee hinter diesem Treiber ist, dass die Nokia-Telefone sich als USB-Modem einbinden lassen und eine virtuelle Netzwerkschnittstelle erstellt wird. Um diese ansprechen zu können, müsste gnokii im Prinzip mit root-Rechten ausgeführt werden. Man kann das jedoch umgehen. Einerseits muss man der gnokii-Applikation etwas mehr Capabilities zugestehen, andererseits muss man dafür sorgen, dass die Schnittstelle automatisch gestartet wird, wenn man das Telefon an den PC anschliesst:

Gnokii Capabilities setzen (als root):
setcap cap_sys_admin,cap_net_raw=+ep $(which gnokii)
setcap cap_sys_admin,cap_net_raw=+ep $(which xgnokii)

Um die virtuelle usbpn-Schnittstelle automatisch zu starten, werden unter Debian/Ubuntu folgende drei Zeilen in der /etc/network/interfaces benötigt:
allow-hotplug usbpn0
iface usbpn0 inet manual
up ifconfig usbpn0 up

Nun muss noch die gnokii-Konfigurationsdatei unter ~/.config/gnokii/config erstellt werden:
[global]
port = usbpn0
connection = phonet
model = series40
[connect_script]
TELEPHONE = 12345678
[disconnect_script]
[logging]
[flags]


Leider hat mich das nicht ernsthaft weiter gebracht. Das Billigst-Telefon (Nokia C1) lässt weiterhin keinen Zugriff auf die SMS-Inbox zu. Telefonbuch auslesen und bearbeiten sowie zumindest SMS versenden klappt sowohl über den AT- wie auch den Phonet-Treiber problemlos.

Nachtrag vom 24.10.: mit Debian Wheezy lässt sich zumindest die Ordnerliste anzeigen, jedoch wird jeder Ordner als leer angezeigt. Das Speichern von SMS funktioniert. SMS lesen scheint aber nach wie vor nicht zu klappen.

Mal wieder Software-RAID retten

^ v M ><
Diesmal handelt es sich um eine Disk aus einem dubiosen NAS. Anscheinend pappt das /dev/sda1 und /dev/sda2 zu einem RAID-1 zusammen. Dies wird wohl so gemacht, um das System elegant aktualisieren zu können. Jedenfalls, musste da mal Hand an die Systemdaten angelegt werden.

Nun, Standardübung, nehmen wir mdadm:
mdadm --assemble /dev/md/0 /dev/sdb1 /dev/sdb2
mdadm: no recogniseable superblock on /dev/sdb1
mdadm: /dev/sdb1 has no superblock - assembly aborted

Wie? Kein Superblock? jaaa aber... parted ist da anderer Meinung:
parted /dev/sdb print
Model: WDC WD10 EARX-00N0YB0 (scsi)
Disk /dev/sdb: 1000GB
Sector size (logical/physical): 512B/512B
Partition Table: gpt

Number Start End Size File system Name Flags
3 15.7MB 528MB 513MB primary
1 528MB 2576MB 2048MB ext3 primary raid
2 2576MB 4624MB 2048MB ext3 primary raid
4 4624MB 1000GB 996GB ext4 primary

Was nun? Es handelt sich hierbei um ein Legacy-RAID ohne Superblock. Das setzt man nicht mit assemble sondern mit build zusammen:
mdadm --build /dev/md/0 --level=1 --raid-devices=2 /dev/sdb1 /dev/sdb2
mdadm: array /dev/md/0 built and started.

Nach der Resynchronisation erfolgt der erste mount-Versuch:
mount /dev/md/0 temp/
mount: unknown filesystem type 'linux_raid_member'

Na gut, erzwingen wir das Dateisystem:
mount /dev/md/0 temp/ -t ext3

Perfekt, alle Daten da :-)

Rewrite Spiele mit Apache

^ v M ><
Das Ziel: Existierende Dateien werden normal angezeigt. Bei nicht existierenden Dateien wird statt Error 404 der Erfolgsstatus 200 und ein Standard-Dokument ausgegeben.

Klingt einfach? Ist es nicht. Das liegt primär daran, dass dafür mod_rewrite braucht, wofür keine gescheite Dokumentation existiert (ist ja schön, wenn die offizielle Doku alle verfügbaren Variablen auflistet, sie aber nirgends erklärt...) und alle bestehenden Howtos irgendwo einen Fehler machen oder diesen zugegebenermassen sehr speziellen Fall überspringen.

So scheitern praktisch alles bestehenden Vorschläge an der fehlerhaften RewriteCond:
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d

-d und -f prüfen aber den absoluten Dateisystempfad, während REQUEST_FILENAME nur den Teil enthält, welcher in der URL nach dem Hostname steht, d.h. http://www.example.com/requested/filename.html. Somit werden diese Rewrite Conditions sowieso niemals zutreffen. Nun gibt es zwei Lösungen dafür. Entweder den ausschliessenden Weg, dass man alle existierenden Dateien von Hand explizit spezifiziert, z.B.
RewriteCond %{REQUEST_FILENAME} !^/robots.txt$
RewriteCond %{REQUEST_FILENAME} !^/favicon.ico$

Nur hat dies zwei Nachteile, es ist aufwändig und unflexibel. Na gut, die simplere Lösung ist es den vorangehenden Pfadnamen hinzuzufügen, dafür gibt es die glücklicherweise vom Namen her sprechende DOCUMENT_ROOT Variable (eine offizielle Dokumentation, wo diese beschrieben wird, ist aus irgendwelchen Gründen schwierig zu finden...), so dass eine funktionierende, flexible und universelle Regel etwa so aussehen könnte:
RewriteEngine on
RewriteCond %{DOCUMENT_ROOT}%{REQUEST_FILENAME} !-d
RewriteCond %{DOCUMENT_ROOT}%{REQUEST_FILENAME} !-f
RewriteRule ^.+$ /index.html [L]


fetchmail via cron

^ v M ><
Hat man fetchmail erfolgreich konfiguriert und als Cronjob ein simples fetchmail -s eingerichtet, so wird sich der Cron Daemon über einen Fehler beschweren, wenn keine Mails im Postfach zur Abholung bereit lagen. Grund dafür ist, dass fetchmail nur 0 als Exit Code zurückgibt, wenn es erfolgreich Mails abgeholt hat. Lagen keine Mails im Postfach, lautet der Exit Code 1, was von Cron völlig berechtigt als Fehler bemängelt wird. Ein kurzes Studium von man fetchmail hat mir dann die Lösung gebracht, der Cronjob ist jetzt folgendermassen konfiguriert:
*/15 * * * * fetchmail -s || [ $? -eq 1 ]

Mehrteiliges rar-Archiv entpacken trotz fehlender Teile

^ v M ><
Der rar-Archiver scheint eine praktische Funktion zu besitzen, nämlich das automatische Splitten beim packen. Ich muss diese Funktionalität mutmassen, da ich rar nicht zum packen verwende, da es unfrei ist. Und überhaupt gibt es in der freien Welt so viele Formate, dass ich dieses problemlos links liegen lassen kann. Jedenfalls resultiert das ganze in Dateien mit der Endung foobar.part1.rar, foobar.part2.rar etc. Das scheint wohl ganz praktisch zu sein für ein very poor man's Backup auf CDs.

Nun hatte ich neulich das Vergnügen, so eine Archivserie zu entpacken, bei welcher eines dieser Teilstücke verloren gegangen ist. Beim packen könnte man wohl angeben, dass ein "recovery volume" angelegt werden soll, womit der Verlust eines Teils kompensiert werden kann. Aber wer denkt schon an sowas ;-) Rar wird nun zwar anfangen zu entpacken, bricht dann aber bei der ersten Datei ab, welche sich (partiell) im verlorenen Teil befindet. Tja, nun hat man also den ersten Teil seines Backups, aber die Daten von hinter dem fehlenden Stück scheinen nicht zugänglich zu sein. Auch eine Suche mit Google hat hier nicht gross weitergeholfen, der Tenor war stets "kannst du vergessen, geht nicht". Aber das stimmt definitiv nicht! Man braucht sich also nicht zu ärgern, dass das Einlesen von 20 CDs oder das herunterladen von 100GB Daten für die Katz war. Zwar kennt rar den Parameter -kb, welcher defekt extrahierte Dateien behalten soll, aber das funktioniert in diesem Fall nicht. Der Entpackvorgang bricht trotzdem ab (hier für Klickibunti-Windosen).

Hier der Trick: Angenommen, part4.rar fehlt. Also erstellt man erst einen scheinbaren Teil 4. Am einfachsten kopiert man einen anderen Teil:
cp foobar.part3.rar foobar.part4.rar
Nun startet man den nächsten Entpackvorgang, schliesst jedoch die als defekt gemeldete(n) Dateien über den exclude-Parameter aus. Wichtig ist die korrekte Syntax zu beachten, nach dem -x darf kein Leerzeichen folgen und Dateinamen mit Leerzeichen müssen zwischen Hochkommata stehen:
unrar x -x'pfad/zu/defekter datei.xls' -x'pfad/zu/ebenfalls defekter datei.doc' foobar.part1.rar
Schon entpackt es weiter.

Natürlich fehlen letztendlich ein paar Daten unwiderbringlich. Aber sofern es sich um eine Notrekonstruktion aus einem defekten "very poor man's" Backup handelt, ist das doch schon besser als gar nichts mehr zu haben.

Ubuntu 11.10 auf Rechnern mit EFI installieren

^ v M ><
Vor etwa einem Jahr habe ich mir einen neuen Server zusammengebaut. Eigentlich wollte ich damals eine CPU, welche drei Anforderungen erfüllt: x86 64bit, virtualisierungsfähig und sehr stromsparend. Leider konnte jede vorhandene CPU höchstens zwei der Kriterien erfüllen, insbesondere bei Intels Atom sind auch heute noch Punkt eins und zwei gegenseitig ausgeschlossen. Und das stromsparendste von AMD war der Athlon X2 240e, welchen ich zuletzt ausgewählt hatte. Monate später wurden dann die Atom-Konkurrenten von AMD veröffentlicht. Zwei Geräte für Tests mit Cluster- und sonstigen Basteleien mit einer derartigen Zacate-CPU habe ich mir nun besorgt, und zwar zwei ZBOXen von Zotac. Diese sind extrem günstig, komplett ausgestattet und befreit von Microsoftsteuern. Zum einen habe ich mir einen Nano gekauft, da dieser mit Fernbedienung geliefert wird, so dass ich diesen später zu einem Multimediarechner umfunktionieren kann. Und zum anderen einen ADO2, da dieser im Gegensatz zum Nano Platz für zwei Speichermodule bietet, so dass er auf 8GB RAM ausgebaut werden kann.

Bei so schönen Geräten muss natürlich erst mal die Hardware etwas genauer getestet werden, statt sie nur im Konsolenmodus zu betreiben. Dazu wollte ich ein paar Betriebssysteme installieren. Ubuntu Desktop 11.10 lässt sich fast problemlos installieren. Die Installation von Ubuntu Server 11.10, Debian 6 und CentOS 6.2 scheitert jedoch an einem Punkt: Beim Laden des Installers geht plötzlich die Tastatur verloren. Natürlich kann jedes Huhn Debian installieren, wenn genügend Körner auf der Tastatur liegen. Aber die Tastatur muss halt funktionieren. Interessanter- und glücklicherweise tritt das Problem beim Ubuntu Desktop nicht auf, so, dass sich dieser mässig bequem installieren lässt.

Das Problem mit den USB-Tastaturen lässt sich auch mit keiner BIOS bzw EFI-Konfiguration beheben. Ich habe alle USB-Einstellungen in jeder Kombination getestet, in letzter Verzweiflung sogar USB-Legacy deaktiviert. Dazu steht im BIOS-Setup, dass dadurch USB-Geräte nur noch in EFI-Applikationen zur Verfügung gestellt würden. Tja, das BIOS-Setup ist blöderweise keine EFI-Applikation, so dass ich nun ganz ohne Tastatur dastand und dies somit nicht mehr einfach korrigieren konnte. Daher musste ich erst mal das CMOS resetten, was zum Glück recht simpel ist. Man muss die Bodenplatte des Geräts entfernen, d.h. erst die vier Daumenschrauben lösen, welche auch als Standfüsse dienen, und dann an der eingekerbten Ecke den Fingernagel einsetzen und die Bodenplatte herausreissen. Nun hat man Zugriff auf alle relevanten Innereien, d.h. Festplatte, WLAN-Karte und RAM-Sockel, so dass man an dieser Stelle auch einfach ein RAM-Upgrade durchführen kann. Für den Reset muss einfach der gummierte, unbeschriftete Knopf zwischen WLAN- und Speichermodul ein paar Sekunden gedrückt werden. Eine bebilderte Anleitung dafür findet sich leicht, jedoch ist in dieser der Reset-Knopf nicht ersichtlich.

Die Geräte verfügen über kein BIOS sondern das modernere EFI. So schöne Vorteile (wie z.B. richtig grosse Platten ohne Workarounds) das bietet, so wüste Nachteile bei der Bootloader-Installation zieht es mit sich. Zur Installation von Ubuntu bin ich folgendermassen vorgegangen:
  • Zuerst habe ich von meinem bevorzugten Mirror das CD-Image für Ubuntu Live 64bit heruntergeladen und dieses mittels unetbootin auf einen bootbaren USB-Stick geschrieben. Diesen habe ich dann in den Zotac eingsteckt und das Gerät eingeschaltet.
  • Wenn die Startpiepser ertönen (ähnlicher Klang wie die Telefone in 24), ein paar mal auf DEL hämmern, um ins BIOS-Setup zu gelangen. Unter "Boot" muss die Startreihenfolge angepasst werden, so dass zuerst ab USB-Stick gestartet wird.
  • Jetzt erscheint der Bootloader und kann man entweder Ubuntu Live starten und dort das Setup aufrufen oder grad den Installer starten.
  • Die Festplatte muss unbedingt manuell partitioniert werden, denn EFI verlangt eine EFI-Partition. Der gparted-Verschnitt des Ubuntu-Installers legt gleich eine GPT-Partitionstabelle an, so dass als erste Partition eine FAT32-Partition von mindestens 200MB angelegt werden kann. Die Schwierigkeit besteht darin, dieser noch das Flag bios_grub gesetzt werden muss. Unter Ubuntu Live ist das kein Problem, da partitioniert man einfach vorher rasch mit gparted. Wichtig ist, dass man die ganze Platte löscht und eine neue Partitionstabelle vom Typ GPT anlegt.
    Im reinen Installer-Modus wechselt man mittels ctrl-alt-F1 in die Konsole, startet mittels
    $ sudo parted
    eine parted-Shell und setzt das Flag rasch per Kommando
    set 1 bios_grub on
    (tatsächlich habe ich im Arch-Wiki gelesen, dass man das Flag boot setzen muss, aber dann meckern später EFI und grub-installer). Zurück zum Installer gelangt man durch alt-F7.
  • Nun installiert man Ubuntu ganz normal fertig. Bloss neu starten sollte man noch nicht! Zuerst muss grub noch richtig installiert werden. Dazu wechselt man wieder in die Kommandozeile (bzw öffnet eine Shell in Ubuntu Live) und gibt folgende Befehle ein:
    $ sudo mount /dev/sda2 /mnt (/dev/sda2 muss ggf durch die korrekte Angabe für die Root-Partition ersetzt werden) und
    $ sudo grub-install --root-directory=/mnt /dev/sda (auch hier muss /dev/sda ggf durch die korrekte Angabe für die Platte, worauf Ubuntu installiert wurde, ersetzt werden).
  • Jetzt kann man neu starten und Ubuntu sollte fehlerfrei booten. Die EFI-Warnmeldungen bezüglich Bildschirmauflösung und "file not found" kann man ignorieren.


Die Leistung der Geräte ist nicht schlecht. Sogar Nexuiz läuft passabel wenn der proprietäre AMD-Treiber fglrx installiert wird, bei 1024x768 ist es mit 40-70FPS absolut spielbar. Bei höheren Auflösungen kommt die Grafikeinheit aber an den Anschlag.

Debian Backports selbst gemacht

^ v M ><
Ab und zu braucht oder möchte man mal unter Debian Stable ein neueres Programm installieren. Oft findet sich dies in Unstable oder gar Testing, aber leider gibt's dann oft keinen Backport. Das ist aber kein Problem. Meine Backports bau ich anhand dieser Anleitung, mit einigen Ergänzungen. Hier erläutere ich dies am Beispiel des Messengers Pidgin:

Als erstes werden mir root-Rechten die benötigten Abhängigkeiten für den Bau des Pakets installiert:
# aptitude build-dep pidgin


Bis auf weiteres können alle weiteren Schritte als normaler User ausgeführt werden. Als nächstes wird die Source und die Debian-Modifikation von packages.debian.org heruntergeladen und in ein eigens für den Build erstelltes Verzeichnis kopiert:
$ mkdir pidgin
$ cd pidgin
$ wget http://ftp.de.debian.org/debian/pool/main/p/pidgin/pidgin_2.9.0.orig.tar.bz2
$ wget http://ftp.de.debian.org/debian/pool/main/p/pidgin/pidgin_2.9.0-3.debian.tar.gz


Nun wird entpackt:
$ tar -jxf pidgin_2.9.0.orig.tar.bz2
$ cd pidgin-2.9.0
$ tar -zxf ../pidgin_2.9.0-3.debian.tar.gz


Der nächste Schritt ist etwas fummelig. Allenfalls müssen Abhängigkeiten angepasst werden, weil das Debian-Skript eine neuere Version einer Abhängigkeit fordert als nötig und/oder für Debian Stable verfügbar ist. Fehlerhafte Abhängigkeiten können einfach bestimmt werden, indem man den nächsten Schritt ausführt und den Kompiliervorgang versucht zu starten. Zur Bereinigung von Abhängigkeiten mit unnötig hoher Version muss die Datei debian/control bearbeitet werden.
Einige benötigte Abhängigkeiten mit höherer Version lassen sich aus den Backports installieren, dies klappt mittels aptitude -t squeeze-backports install myrequireddependency (vorausgesetzt, das backports-Repository ist konfiguriert). Für einige ganz fiese Abhängigkeiten kann es nötig sein, dass man davon selbst ein Update gemäss dieser Anleitung erstellen und installieren muss.

Sind alle Probleme behoben, kann man nun den Compiler anwerfen lassen:
$ dpkg-buildpackage -rfakeroot -uc -b


Wenn dies erfolgreich war, erhält man ein installationsbereites .deb-Paket. Für die Installation sind natürlich wieder root-Rechte erforderdlich:
$ cd ..
$ su
# dpkg -i *.deb

Mumble 1.2.3 unter Debian Stable

^ v M ><
Bislang gab es relativ gute Pakete für Mumble 1.2.3 aus Debian Experimental, welche sich sauber unter Debian Squeeze installieren liessen. Unterdessen gibt es einen neuen Build, der auch grad das ganze QT aktualisieren will. Da dürfte ein ziemlich defektes System daraus resultieren. Logische konsequenz? Selber bauen natürlich :-)

zuerst das alte Mumble deinstallieren:
aptitude purge mumble


Danach geht's eigentlich streng gemäss Wiki. Als nächstes muss man die benötigten Entwicklungspakete installieren:
apt-get build-dep mumble


Und nun die Source mit den gewünschten Parametern kompilieren. Ich brauch weder Server noch den Mumble 1.1 Clienten. Letzterer wird über den nicht dokumentierten Switch no-11x deaktiviert. Unter Debian werden die Lokalisierungen nicht gefunden und integriert, daher werden diese einfach ausgeschaltet. Vermutlich liesse sich das über Symlinks korrigieren
tar -zxf mumble-1.2.3.tar.gz
cd mumble-1.2.3
qmake-qt4 -recursive main.pro CONFIG+=no-server CONFIG+=no-embed-qt-translations CONFIG+=no-11x
make
su -c 'cp -r release /opt/mumble'
su -c 'cp icons/mumble.xpm /opt/mumble'


Und nun noch die Sache starten:
/opt/mumble/mumble

virt-manager und Debian

^ v M ><
Dank virt-manager kann man auch mit kvm und xen per Klickibunti übers Netzwerk administrieren. Nur, unter Debian kann es vorkommen, dass alles korrekt eingerichtet ist (libvirtd läuft, User ist in der Gruppe libvirtd, /var/run/libvirt/libvirt-sock ist zugreifbar), trotzdem weigert sich der virt-manager mit der Meldung
"Unable to open a connection to the libvirt management daemon. Verify that: - The 'libvirtd' daemon has been started"

Liest man die Meldung weiter, so stösst man auf die Zeile
error: server closed connection: nc: invalid option -- 'U'

Die Lösung: Debian installiert standardmässig netcat-traditional. Das unterstützt aber die Option U nicht. Dafür wird netcat-openbsd benötigt. Folglich kann man das beheben mittels
aptitude install netcat-openbsd


Zum Glück ist Debian Stable ja sooo bugfrei.