Newer posts are loading.
You are at the newest post.
Click here to check if anything new just came in.

August 12 2012

18:12

Trennung vom bash-it Framework - Koche nun eigenes Süppchen

Manchmal muss man das auch. Einige Zeit hab ich Hirnschmalz in das Community Framework bash-it gesteckt.

Anfangs mit der aktiven Weiterentwicklung beschäftigt, hab ich später eher massiv Aufwand betreiben müssen um die neuen Dinge mit meiner Version kompatibel zu halten. Man konnte bash-it früher entweder komplett als eine Art Distribution für die Bash benutzen, oder sich wie in einer Art Supermarkt an einzelnen Schnipseln, Funktionen und kleinen Skripten bedienen die man gut fand. Und das war super. Man konnte Dinge lernen, Schnippsel von anderen adaptieren und hatte immer Trickreiche Funktionen am Start.

Der Rip-Off von oh-my-zsh hat sich aber mit der Zeit (und Dank der großen Aktivität der Community) m.E. zu einem für mich nicht mehr funktionierendem Konzept entwickelt. Konkret:

  • Die Überarbeitung des Plugin Systems mit Meta Informationen war ein riesen Fehler
  • Aktivierung und Deaktivierung einzelner Komponenten ist unnötig und verwirrend für neue User (und für mich auch.. :P )
  • Etwas, dass ich gerne den “theme-color-vcs-prompt-complex” nenne. Aber das würde den Rahmen sprengen…
  • Der Wust aus 1. Mio Dingen, den mittlerweile niemand (mehr) braucht/versteht
  • Fehlende Ziele/grobe Richtung für die Entwicklung
  • Durch die stark wachsende Komplexität funktioniert bash-it nichtmal mehr als Supermarkt Bedienkonzept.
  • Ca. 5 Sekunden bis zum Prompt

All diese Probleme und Punkte haben mich dazu veranlasst, meine eigene Suppe zu kochen, die ich in meiner gnadenlosen Unkreativität nano-bash genannt habe. Es hat einen ganzen Nachmittag gedauert die wenigen Dinge die ich wirklich brauche aus bash-it zu extrahieren und aus Funktionen zu lösen, damit das Ganze in eine neue (für mich pflegbare) Form passt. Denke das spricht auch schon für sich…

Schade :(

July 29 2012

15:39

*.wma zu *.mp3

Man denkt ja immer “Gott, wie viele von diesen $MUSIKFORMAT_A zu $MUSIKFORMAT_B Formatierungsblogposts kann mein Reader eigentlich vertragen”. Das denkt man zumindest so lange, bis man mal in die Verlegenheit gerät sowas zu brauchen.

Tatsächlich ist das alles andere als einfach. In 90% der Szenarien werden 0815 Probleme gelöst wie:

Ich möchte gerne ein Lied konvertieren. Wie geht das?

Dankeschön. Eins. Ich muss hier 25% meiner f*cking Musikbibliothek converten. Warum finde ich daüber keine Blogposts?

Naja. Dann eben selbst. Der Plan ist einfach. Verzeichnisse herausfinden, die *.wma Dateien enthalten und in eine Liste schreiben.

1
2
3
4
5
OIFS=$IFS
IFS=$'
'
for i in $(find . -type f -iname '*.wma'); do 
  dirname $i
done | sort | uniq > list.txt

Diese Liste mit Verzeichnissen abarbeiten, sodass ich die Lösung die ich im UbuntuUsers-Wiki gefunden habe einbetten kann:

1
2
3
4
5
6
7
8
9
10
11
for x in $(cat list.txt) ; do 
  cd $x
  for i in *.wma ; do 
    mplayer -vo null -vc  dummy -af resample=44100 -ao pcm:waveheader "$i"
    lame --preset standard audiodump.wav -o "`basename "$i" .wma`.mp3"
    rm -f $i
  done
  rm -f audiodump.wav
  cd - &>/dev/null
done 
IFS=$OIFS

Das wurde gerade im Basis Verzeichnis meiner Biblio gestartet und rödelt jetzt erstmal vor sich hin. Obacht, gerade die IFS Umgebungsvariable ist bei dieser Variante extrem wichtig.

Eigentlich will man eher *.ogg. Würd ich auch echt gern. Aber mein mobiles Abspielgerät will nicht.

July 02 2012

19:00

Paying 5 bucks a month for stupid statistics?

Seit ich angefangen habe Ausflüge durch Wälder und anderem grobem Gelände mit meinem Mountainbike zu machen ist Runkeeper mein Begleiter.

Mit der iPhone App kann ich allerhand Daten tracken wie

  • Durchschnittliche Geschwindigkeit
  • Höhenmeter
  • Kalorien (wenn man deren Berechnungen glauben mag)
  • Karten
  • Länge der Fahrt

Natürlich will auch Runkeeper irgendwie Geld verdienen und somit gibt es was Accounts angeht auch noch einen “Elite Pro Wahnsinns” Account welcher irgendwie 5-8 Euro im Monat kostet und mir als Ausgleich bessere Statistiken und sogenannte “Fitness Reports” liefert.

Ehrlichgesagt war ich davon nicht sehr angetan so viel Geld für ein paar extra Skripte zu bezahlen. Deshalb hab ich mich entschlossen meine eigenen Graphen mit GnuPlot zu malen und irgendwie zu einer Website zu machen.

runkeeper-statistics

Im Grunde liefert mir Runkeeper alle Rohdaten die ich brauche. Sie weigern sich nur mir die Statistiken daraus zu bauen die gerne hätte. Ich habe mir dann ein Shell Script gebaut, welches gnuplot mit Daten füttert, die in einem CSV File spezifiziert sind.

Zuerst schreibe ich alle meine Daten in die activity.dat. Ziemlich im CSV Stil, aber mir fiel nicht blöderes ein ohne SQL sprechen zu müssen.

1
2
3
4
5
6
# Add your data here to generate awesome graphs ;) 
# ID, Date,      Distance, Duration, Pace, Speed, Burned, Climb
  1,  2012-06-23, 14.07,    0.54,     3.54, 15.38, 458,    156
  2,  2012-06-26, 16.28,    1.09,     4.17, 14.03, 582,    292
  3,  2012-06-28, 17.65,    1.13,     4.11, 14.36, 618,    242
  4,  2012-06-30, 27.28,    1.47,     3.56, 15.24, 876,    379

Danach baut mir das Shellscript die GnuPlots und die HTML Site

1
$ ./runkeeper-statistics

Das alles gibts auf github und die “Demo” hab ich mal hochgeladen und mit zufälligen Daten befüllt:Demo

June 16 2012

10:31

Stromverbrauch für Nerds mit Google Charts

Seit nun ca. 8 Monaten wohne ich nicht mehr bei meinen Eltern. Wenn man Zuhause auszieht kommen immer ein Haufen neuer Aufgaben auf einen zu. Unter anderem auch den Verbrauch des Stroms regelmäßig abzulesen und zu notieren.

Ich wollte wenn’s irgendwie geht vermeiden irgendein Excel File zu pflegen oder das einfach nur auf Papier zu schreiben. Also habe ich den Weg für Statistik Nerds via Google Charts gewählt.

Konkret schick ich per JavaScript meine Daten zu einer Google API und daraus werden dann wunderschöne(!), interaktive(!) Graphen in den Browser gezaubert.

Am Anfang gibts erstmal einen Konfigurationsabschnitt. Dort trage ich die Werte ein definiere Variablen. Ich habe hier zu Demonstrationszwecken relativ zufällige Zahlen eingefügt.

Konfigurationsabschnitt
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
<script type="text/javascript" src="https://www.google.com/jsapi"></script>
<script type="text/javascript">
  // Zaehlerstaende 
  var g31082011 = 131079;
  var g30092011 = 131259;
  var g31102011 = 131445;
  var g31112011 = 132014;
  var g31122011 = 132150;
  var g31012012 = 132386;
  var g29022012 = 132804;
  var g31032012 = 133305;
  var g30042012 = 133514;
  var g30052012 = 133811;
  // Werte bzw. Differenzen errechnen  
  var d30092011 = g30092011 - g31082011;
  var d31102011 = g31102011 - g30092011;
  var d31112011 = g31112011 - g31102011;
  var d31122011 = g31122011 - g31112011;
  var d31012012 = g31012012 - g31122011;
  var d29022012 = g29022012 - g31012012;
  var d31032012 = g31032012 - g29022012;
  var d30042012 = g30042012 - g31032012;
  var d30052012 = g30052012 - g30042012;
  // Preis pro kWh 
  var kwhpreis = 0.23;
</script>

Das alles fülle ich dann in die Data Arrays der Google Chart Funktion ein, definiere eine div id und beschrifte die Spalten und den Graphen an sich.

horizontales Balkendiagramm
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
<script type="text/javascript">
  google.load("visualization", "1", {packages:["corechart"]});
  google.setOnLoadCallback(drawChart);
  function drawChart() {
    var data = new google.visualization.DataTable();
    data.addColumn('string', 'Date');
    data.addColumn('number', 'kWh');
    data.addRows([
      ['30.09.2011',    d30092011],
      ['30.10.2011',    d31102011],
      ['31.11.2011',    d31112011],
      ['31.12.2011',    d31122011],
      ['31.01.2012',    d31012012],
      ['29.02.2012',    d29022012],
      ['31.03.2012',    d31032012],
      ['30.04.2012',    d30042012],
      ['30.05.2012',    d30052012],
    ]);
     var options = {
      width: 550, height: 300,
      title: 'Monatlicher Stromverbrauch in kWh',
      vAxis: {title: 'Datum'}
    };
 var chart = new google.visualization.BarChart(document.getElementById('barchart_div'));
 chart.draw(data, options);
 }
</script>

Wenn alles fertig befüllt ist wird die .js Funktion clientseitig ausgeführt und somit eine Anfrage an die Google Charts API gestellt. Was diese dann antwortet sieht man hier:

So oder so ähnlich befülle ich dann auch alle anderen Funktionen die nötig sind um mir andere Graphen bauen zu lassen. Im Grunde ist es jedesmal nur das Einfügen von Variablen in ein Array. Die eigentliche Google Magie in den Funktionen kann man sich sehr einfach auf der Google Page zusammen klicken.

Ein wunderbar nichts sagendes Tortendiagramm darf natürlich nicht fehlen.

Ich hab mir auch noch einen Graphen gebaut der mir gleich noch die vorraussichtlichen Preise pro Monat errechnet.

Hier gibts das File, so wie ich es bei mir lokal Pflege. Da kann man auch nochmal genau den Source ansehen, wie welche Funktion befüllt werden muss. Und gerade weil das so schön .js ist, kann man das auch wunderbar in seinen Blog einbinden, cool mh?

May 28 2012

12:41

Apache 2.4 und mpm_event

Apache 2.4 ist seit einiger Zeit in Debian Experimental paktiert. Yeah!

Grade das eventbasierte MPM mpm_event, dass in 2.4 stable wird hat mich daran interessiert. Zeit mal wieder Graphen zu bauen und Benchmarks anzustoßen.

Das Setup

Getestet werden:

  • MPM prefork Apache2 (2.2, Debian Stable)
  • MPM worker Apache2 (2.2, Debian Stable)
  • MPM event Apache2 (2.4, Debian Experimental)

Um möglichst genaue Daten zu bekommen hab ich keine Maschine gewählt auf der ich per Datenkabel erst hin muss um so leitungsverschuldete Messfehler zu vermeiden. Für die Tests musste jeweils ein LinuXContainer auf meinem Thinkpad herhalten.

Eckdaten des Tests:

  • Debian Minimal Installation
  • 4x Prozessoren (i5)
  • 4GB RAM
  • Netzwerk über eine lokale Ethernet Bridge
  • Auslieferung der Apache2 Default HTML Page
  • Konfigurationen der MPMs alle Paket default behalten
  • Alle Benchmarks sind mit ab durchgeführt. Dieses Apache Benchmark Tool wird mit dem Paket apache2-utils ausgeliefert.

Max Requests

Ein typischer Apache Bench mit ab sieht ungefähr so aus:

1
$ ab -c 200 -n 2500 http://host.example.org/
  • -c gibt die Anzahl der gleichzeitigen Verbindungen an
  • -n Die Anzahl der Connections insgesamt

Jedem Apache habe ich nun stufenweise Connections hingeschossen und mir die Dauer jedes Benchmarks weggegreppt:

1
2
3
4
5
6
C=0
while [ $C -lt 100000 ]; do 
  C=$((C + 10000))
  echo -n "$C:"
  ab -c 500 -n $C http://10.10.0.16/ 2>/dev/null | grep "Time taken for tests:" | awk '{print $5}'
done

Das hab ich für jeden Host einzelnd durchgeführt und anschliessend alles durch Gnuplot gejagt. Dabei kam einmal mehr zum Vorschein, dass man Prefork einfach nicht haben möchte :)

Max Concurrency

Natürlich haben die verschiedenen Modelle verschiedene Eigenschaften die sie für bestimmte Aufgaben tauglicher macht als andere. Deshalb hab ich auch noch von 100-1000 gleichzeitigen Requests geprüft. Der Einzeiler ist dafür nur geringfügig modifiziert:

1
2
3
4
5
6
C=0
while [ $C -lt 1000 ]; do 
  C=$((C + 100))
  echo -n "$C:"
  ab -c $C -n $C http://10.10.0.16/ 2>/dev/null | grep "Time taken for tests:" | awk '{print $5}'
done

Das Ergebnis von MPM Event kann sich sehen lassen, wie ich finde.

Warum MPM Prefork bei 1000 gleichzeitigen Connections immer so “abhaut” kann ich nicht sagen. Habs mehrmals versucht mit immer dem gleichen Ergebnis.

Fazit

Die Daten zu deuten ist jedem selber überlassen. Was hier auch überhaupt nicht zur Sprache kam ist die Administrierbarkeit der Module oder Stabilität. Ob man Prefork mag weil es nativ mit mod_php kann oder man sich wegen der Performance mpm_worker mit fcgid antut… Geschmäcker gehen hier außeinander aber allein wegen der Verträglichkeit des mpm_event gegenüber Slowloris Attacken sollten man sich den “neuen” mpm_event jedenfalls mal ansehen. Performacetechnisch sieht es jedenfalls nicht schlecht aus ;)

Wer möchte kann sich die Rohdaten der Tests bei Github abholen.

Den Source zu den Plots gibts auf Nachfrage ebenfalls.

May 14 2012

13:30

LXC. Not ready yet for production use, huh?

Von LinuX Containern hab ich zum ersten Mal auf den Linux Tagen im Vortrag von Erkan Yanar gehört.

Kurz gesagt ist LXC größtenteils eine Sammlung von Skripten welche in soetwas wie einem chroot einen neuen init-Prozess spawnen. Das bietet mit cgroups in eigenen Namespaces auch eine Art dynamische Ressourcen Zuweisung.

Dafür gibts jetzt verschiedene Use-Cases. Bei mir ist das sowas wie eine Art Sandboxing für Spielereien auf meinem Thinkpad.

I said before that in my opinion LXC is not ready yet for production use, and I
maintain that opinion today. I would also rephrase it in something that might
make it easier to understand what I think: I would never trust root on a
container to somebody I wouldn’t trust root with on the host.

Diego Elio “Flameeyes” Pettenò, blog.flameeyes.eu

Das Zitat triffts eigentlich recht gut auf den Punkt. Besonders gefährlich ist das gemeinsam genutzte /dev und /proc Verzeichnis, wobei es unter Umständen auch einfach möglich ist die gesamte Maschine herunterzufahren. Deshalb würde ich davon abraten virtuelle Maschinen an Dritte abzugeben.

LXC: Debian Stable oder Testing?

Trotz allem reizt mich das Thema. Installiert wird das wie so ziemlich alles über

1
$ apt-get install lxc bridge-utils debootstrap

Allerdings gibt es bei testing und auch bei stable Nachteile.

1
2
3
4
5
6
7
8
9
10
$ apt-cache policy lxc
lxc:
  Installiert: 0.7.2-1
  Kandidat:    0.7.2-1
  Versionstabelle:
     0.8.0~rc1-4 0
        500 ftp://ftp.de.debian.org/debian/ testing/main amd64 Packages
 *** 0.7.2-1 0
        990 http://ftp.uni-erlangen.de/debian/ squeeze/main amd64 Packages
        100 /var/lib/dpkg/status
  • Testing: Im Moment scheinen die cgroups kaputt. Dafür konnte ich keine Lösung finden da ich auch noch keine Erfahrung mit cgroups habe. Schade. Verison 0.8 hätte mich gereizt.
1
2
3
4
$ lxc-start --name vm0
lxc-start: No such file or directory - failed to rename cgroup /sys/fs/cgroup//14051->/sys/fs/cgroup//vm0/14051
lxc-start: failed to spawn 'vm0'
lxc-start: No such file or directory - failed to remove cgroup '/sys/fs/cgroup//vm0/14051'
  • Stable: Unter Stable ist kein Template für Debian Squeeze verfügbar. Da heissts dann Lenny Template umbauen. Anleitung ist recht einfach zu verstehen und funktioniert.

Networking über WLAN

Das mit dem normalen Bridiging über WLAN Interfaces haut erfahrungsgemäß nicht hin. Deshalb hab ich mir hier etwas helfen lassen. Meine Config sieht und in etwa so aus:

1
2
3
4
5
6
7
auto lxcbr0
iface lxcbr0 inet static
  address 10.10.0.1
  netmask 255.255.255.0
  pre-up brctl addbr lxcbr0
  post-up /usr/local/bin/lxcbr0-up
  post-down brctl delbr lxcbr0
1
2
3
4
5
6
7
8
9
10
$ cat /usr/local/bin/lxcbr0-up
#!/bin/sh
# This is the address we assigned to our bridge in /etc/network/interfaces
braddr=10.10.0.1
# ip address range for containers
brrange=10.10.0.10,10.10.0.100
iptables -A FORWARD -i lxcbr0 -s ${braddr}/24 -m conntrack --ctstate NEW -j ACCEPT
iptables -A FORWARD -m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPT
iptables -A POSTROUTING -t nat -j MASQUERADE 
dnsmasq --bind-interfaces --conf-file= --listen-address $braddr --except-interface lo --dhcp-range $brrange --dhcp-lease-max=253 --dhcp-no-override

Wenn man das ohne DHCP möchte geht das auch einfach so - ohne Umkonfiguration :)

Mass-LXC

Ich möchte meine Linux Container nun immer in einem screen starten. Ein Start sieht daher ungefähr immer so aus:

1
$ screen -d -m -S vm0 lxc-start -n vm0 -f /var/lib/lxc/vm0/config

Aus erst einem Alias wurden dann Mehrere und dann ein Wrapper Script mit dem ich Infos und Start/Stops für alle VMs auslesen/anweisen kann. Ich muss zugeben es ist etwas ausgeartet. Das Script ist wie immer auf Github zu haben. Unter Umständen kann nochjemand etwas damit anfangen.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
$ mlxc info
Screens:
No Sockets found in /var/run/screen/S-root.

LXC Status:
'vm0' is STOPPED
'vm1' is STOPPED
'vm2-mysqld' is STOPPED
'vm3-postgresql' is STOPPED
'vm4-matomat' is STOPPED

$ mlxc all
$ mlxc info
Screens:
There are screens on:
  8682.vm0  (14.05.2012 15:29:47) (Detached)
  8686.vm1  (14.05.2012 15:29:47) (Detached)
  8690.vm2-mysqld (14.05.2012 15:29:47) (Detached)
  8694.vm3-postgresql (14.05.2012 15:29:47) (Detached)
  8698.vm4-matomat  (14.05.2012 15:29:47) (Detached)
5 Sockets in /var/run/screen/S-root.

LXC Status:
'vm0' is RUNNING
'vm1' is RUNNING
'vm2-mysqld' is RUNNING
'vm3-postgresql' is RUNNING
'vm4-matomat' is RUNNING

$ mlxc net
Netstat for vm0:
IP: 10.10.0.10
Aktive Internetverbindungen (Server und stehende Verbindungen)
Proto Recv-Q Send-Q Local Address           Foreign Address         State       PID/Program name
tcp        0      0 0.0.0.0:22              0.0.0.0:*               LISTEN      10815/sshd      
tcp        0      0 127.0.0.1:25            0.0.0.0:*               LISTEN      10728/master    
[...]

Auf Ideen, Anmerkungen, Kritik und Beleidigungen freu ich mich natürlich immer.

May 07 2012

noqqe
18:57
2375 22db
Reposted fromgivota givota viavideogames videogames

May 06 2012

19:51

Deadly 30 unter Debian Squeeze 64bit

Gerade von Deadly 30 gelesen. Linux Version ist fertig. Hurra!

Als ich den Trailer gesehen habe musste ich sofort an die Metal Slug Reihe denken, die ich total mag.

Egal, es ist Sonntag Abend und hatte die 4 Euro übrig. Ich hatte aber bereits erwartet, dass es nicht nur auf ein ./deadly 30 hinauslaufen würde. Damit lag ich auch richtig.

1
2
3
$ ./Deadly 30
./Deadly 30: error while loading shared libraries: libgstreamer-0.10.so.0:
cannot open shared object file: No such file or directory

Mh. Da ich nicht zwischen 32 und 64bit wählen durfte wahrscheinlich 32bit?

1
2
3
$ file Deadly 30                                                                                                                 
Deadly 30: ELF 32-bit LSB executable, Intel 80386, version 1 (SYSV), dynamically
linked (uses shared libs), for GNU/Linux 2.6.15, stripped

Also die nötigen 32bit Libraries runterladen und einbauen.

1. /usr/lib32/ Backup erstellen

1
$ tar cfvz $HOME/usr-lib32.tar.gz /usr/lib32

2. libgstreamer installieren

1
2
3
4
5
$ cd /tmp
$ wget http://ftp.de.debian.org/debian/pool/main/g/gstreamer0.10/libgstreamer0.10-0_0.10.30-1_i386.deb
$ ar -x libgstreamer0.10-0_0.10.30-1_i386.deb
$ tar xfvz data.tar.gz
$ sudo cp -av /tmp/usr/lib/* /usr/lib32/

3. libgstreamer-plugins installieren

1
2
3
4
5
$ cd /tmp
$ wget http://ftp.de.debian.org/debian/pool/main/g/gst-plugins-base0.10/libgstreamer-plugins-base0.10-0_0.10.30-1_i386.deb 
$ ar -x libgstreamer-plugins-base0.10-0_0.10.30-1_i386.deb 
$ tar xfvz data.tar.gz
$ sudo cp -av /tmp/usr/lib/* /usr/lib32/

Das ist zwar alles immer total unschön, aber es funktioniert. Außerdem, was tut man nicht alles für ein bisschen 2D Shooter und Zombies?

May 05 2012

09:33

Ext Filesystem Checks vorhersagen

Kernel Updates am Server seiner Wahl einspielen und dann…warten. Warten auf die erlösenden ICMP Antworten. Oder bootet die Kiste doch nicht? Alles dauert verdächtig lange. Auch nach 10 Minuten noch nichts. Gerade wenn man die Zugangsdaten fürs DRAC/ILO rausgekramt hat zeigt sich: Filesystem Check.

Extended Filesystems machen an den folgenden 2 Punkten fest wann fsck’s passieren:

  • Maximale Anzahl von Mounts
  • Zeitliche Abstände zwischen den Routine Checks

Die Informationen stehen im Superblock einer Parition. Das Tool dumpe2fs stellt diese zur Verfügung:

$ dumpe2fs -h /dev/sda1 

Das ganze hab ich dann verskriptet. Es “scanned” alle gemounteten ext Parititonen und warnt einen, falls die maximalen Mounts oder die zyklischen Checks anstehen.

#!/bin/bash
# ext-verify: Verfiy if max mount count or cyclic fsck 
# on ext2,ext3,ext4 filesystems has been reached. 
# Copyright: (C) 2011 Florian Baumann <florian.baumann@noris.net>
# License: GPL-3 <http://www.gnu.org/licenses/gpl-3.0.txt>
# Date: Tuesday 2012-05-04

# Configuration
DUMPE2FS=$(which dumpe2fs)
DUMPOPTS="-h"
WARNC=0

# Security 
if [ -z "$DUMPE2FS" ]; then
    if [ ! -x $DUMPE2FS ]; then
        echo "ERR: Could not find your dumpe2fs"
        echo "ERR: Are you root?"
        exit 1
    fi
fi

# Parsing functions
function get_value () {
    LANG=C $DUMPE2FS $DUMPOPTS $HDD 2>/dev/null | grep "$1" | sed "s#$1s*##" | tail -1
    if [ $? -gt 0 ]; then echo "ERR: Could not find value $1" ; fi
}
function convert_date () {
    if [ -n "$1" ]; then
        date -d "$1" "+%s"
    fi
}

# Scan Mode
if [ -z "$*" ]; then
    for x in $(mount | grep ext | awk '{print $1}'); do
        HDD=$x
        MOUNTED=$(get_value "Mount count:")
        MAXMOUNT=$(get_value "Maximum mount count:")
        NEXT=$(get_value "Next check after:")
        DATENOW="$(date +%s)"
        DATENEXT=$(convert_date "$NEXT")

        if [ ! "$MAXMOUNT" == "-1" ]; then
                if [ $MOUNTED -ge $MAXMOUNT ]; then
                        echo "WARNING: Max mount count on $HDD has been reached. ($MOUNTED/$MAXMOUNT)"  
                        ((WARNC++))
                fi
        fi

        if [ -n "$DATENEXT" ]; then
                if [ $DATENOW -ge $DATENEXT ]; then
                        echo "WARNING: $HDD has reached the next periodically filesystemcheck. ($NEXT)"
                        ((WARNC++))
                fi
        fi

        if [ $WARNC -gt 0 ]; then
            echo "RESULT: A fsck will be executed at the next reboot for $HDD."  
        else
            echo "RESULT: Everything's fine on $HDD."
        fi
    done
fi

exit $WARNC

Das sieht dann unter Umständen so aus:

1
2
3
WARNING: Max mount count on /dev/sda1 has been reached. (29/29)
WARNING: /dev/sda1 has reached the next periodically filesystemcheck. (Sa Apr 7 13:37:58 2012)
RESULT: A fsck will be executed at the next reboot for /dev/sda1.

Natürlich für jede gefundene Partition. Um das jetzt noch am besten irgendwie zu automatisieren hab ich mich entschieden das in apt zu integrieren.

1
2
$ vim /etc/apt/apt.conf.d/09extverfiy
DPkg::Pre-Install-Pkgs   { "if [ -x /usr/local/bin/ext-verify.sh ]; then echo 'Verifying ext Filesystems' ; /usr/local/bin/ext-verify.sh ; fi"; };

Bei jedem apt-get/aptitude wird das nun ausgeführt.

1
2
3
4
5
6
7
8
9
10
11
12
$ aptitude install whois
Die folgenden NEUEN Pakete werden zusätzlich installiert:
  whois
0 Pakete aktualisiert, 1 zusätzlich installiert, 0 werden entfernt und 0 nicht aktualisiert.
Muss 0 B/64,9 kB an Archiven herunterladen. Nach dem Entpacken werden 406 kB zusätzlich belegt sein.
Verifying ext Filesystems
RESULT: Everything's fine on /dev/sda1.
Vormals abgewähltes Paket whois wird gewählt.
(Lese Datenbank ... 48680 Dateien und Verzeichnisse sind derzeit installiert.)
Entpacken von whois (aus .../whois_5.0.10_amd64.deb) ...
Trigger für man-db werden verarbeitet ...
whois (5.0.10) wird eingerichtet ...

April 29 2012

10:22

Das CAP Theorem

Das CAP Theorem ist mir das erste mal wirklich begegnet im Podcast Binärgewitter #1 NoSQL in dem es kurz und knackig an einfachen Beispielen gut erklärt wurde.

Im Grunde hat sich schon kurz nach der Jahrtausendwende ein Professor in Berkeley Gedanken gemacht was man von einem Datenbank System erwarten kann. Im wesentlichen gehts um 3 Faktoren, die aber niemals alle zugleich erfüllt werden können.

Konsistenz (C): Alle Knoten sehen zur selben Zeit dieselben Daten.
Verfügbarkeit (A): Alle Anfragen an das System werden stets beantwortet.
Partitionstoleranz (P): Das System arbeitet auch bei Verlust von Nachrichten, einzelner Netzknoten oder Partition des Netzes weiter.

Will man sich mal anschauen, wenn man Datenbanken betreut.

Links

April 20 2012

06:52

Keyboard Codes unter Debian mit xfce4.8

Zuerstmal sei gesagt, dass ich sowieso schon sehr begeistert bin wie viele von den Spezialtasten auf dem Thinkpad schon Out-of-the-Box unter Debian funktionieren. Trotzdem gab es noch ein paar die das nicht Taten oder zumindest nicht mit der Software funktioniert hatte bei der ich es brauche.

Keyboard Signale mit xev abfangen

Erstmal gehts darum rauszufinden was für lustige Tasten ich eigentlich gerade drücke. Hier gibts verschiedene Spielereien mit dem Tool xev und sed:

$ xev | sed -n 's/^.*keycode *([0-9]+).*$/keycode  /p' 
keycode 36 
keycode 8 
keycode 160 
keycode 160 

XKeysymDB und benutzerdefiniertes Mapping

Nachdem man weiss, was für KeyCodes man gerade drückt kann man damit auch weiter arbeiten. Diese KeyCodes müssen nun Keysyms zugeordnet werden. Der X11 bringt hier automatisch eine kleine Übersicht mit die es sich lohnt mal anzusehen:

$ less /usr/share/X11/XKeysymDB

Obacht: Man kann keine neuen Keysyms definieren. Man muss Keysyms aus dem DB File benutzen um diese dann auf den Keycode zu mappen. Dieses Mapping findet folgendem File statt:

$ vim ~/.Xmodmap 
keycode 160 = hpModelock1 

Anschliessend kann man die Xmodmap neu laden:

$ xmodmap ~/.Xmodmap 

xfce Keymapping

Der eigentlich spannende Teil ist, die Shortcuts jetzt mit xfce zu verknüpfen, damit man bei Betätigung einen Befehl seiner Wahl ausführen kann. In xfce gibt es eine kleine gui im Settings Manager (xfce4-settings-manager) mit der man soetwas einrichten kann. Zumindest theoretisch. Leider können hier nur Tastenkombinationen(!) hinterlegt werden. Keine Keysyms.

Aber das macht nichts. Wie so ziemlich alles gibts ein xml File in dem die Werte stehen:

$ vim .config/xfce4/xfconf/xfce-perchannel-xml/xfce4-keyboard-shortcuts.xml 
xfce4-keyboard-shortcuts.xml
1
2
3
4
5
6
7
<property name="custom" type="empty">
  <property name="&lt;Alt&gt;F2" type="string" value="xfrun4"/>
  <property name="&lt;Control&gt;&lt;Alt&gt;Delete" type="string" value="xflock4"/>
  <property name="XF86Display" type="string" value="xrandr --auto"/>
  <property name="override" type="bool" value="true"/>
  <property name="hpModelock1" type="string" value="/usr/bin/i3lock"/>
</property>

Der letzte Eintrag wurde von mir per Hand eingetragen und funktioniert. Mit fn+F2 kann ich jetzt (wie auf meinem Keyboard belabelt) meinen Bildschirm sperren.

Links

http://en.gentoo-wiki.com/wiki/Multimedia_Keys

http://wiki.ubuntuusers.de/Xmodmap

http://wiki.xfce.org/faq#keyboard

April 15 2012

09:16

Thinkpad X201

Ich erstand bei ralf-scharbert.de ein Thinkpad X201 (refurbished) für einen m.E. guten Preis.

Alles ist toll, Debian installiert, Funktionstasten gehen fast alle Out-of-the-Box. Nur das wlan musste kurz nachgebaut werden, weil non-free Firmware:

$ apt-get install firmware-iwlwifi

Wenn ich mich jetzt noch dran gewöhnen könnte den roten Nippel zu nutzen statt das kleine Touchpad ist alles gut. Zumindest wurde mir das Nahe gelegt ;)

Um das zu Windows 7 zu sichern (sollte ich es mal brauchen) hab ich außerdem mal die Windows Image Sicherung ausprobiert. Konkret auf ein CIFS Share im Netzwerk die .VHD Files überspielt und aus dem Internet den “Windows Systemrettungsdatenträger” geholt :). Habe nicht probiert ob das wirklich funktioniert, aber es klingt zumindest so als könne man sich darauf verlassen.

Hurra.

April 09 2012

18:05

DaviCal, PostgreSQL und Apple Produkte

Vor ewigen Zeiten hab ich mir mal ein eGroupware installiert. Es war schrecklich und deshalb hab ich es durch etwas weniger Schreckliches ersetzt. DaviCal.

Nicht das ich spontan Lust gehabt hätte sowas wie Kontakte und so mal zu Ordnen. Vielmehr hat mich die PostgreSQL Datenbank intressiert die dazu nötig ist. Installation und Konfiguration ist so schön dokumentiert das ich das hier nicht widerholen brauche. Die Integration in Thunderbird verlief ohne Probleme. Dann kamen meine beiden Geräte aus dem Hause Crapple mit der Synchronisation der Kontakte dran.

iPhone

Mein iPhone wollte den hingeworfenen Remote für Contacts nicht einfach so hinnehmen. Ewiges “Verifying” durch den Installationsassistenten und jedesmal gefühlte 5-10 Minuten später hat er mich dann abgewiesen. Im Apache Log ist davon nichts aufgetaucht. Nach bisschen wälzen in der Dokumentation hier und da:

CardDav-Accounts only could set up via iPhone configuration utility. It had to
set up a principal url (e.g. https://domain.tld/caldav.php/username/contacts)
for a working account.

Carddav Clients, wiki.davical.org

Das iPhone configuration utility also. So ganz leicht fand ich das damit nicht… Ich hab aber gelernt das man super Debuggen kann über die eingebaute Consolen Funktion in dem Tool. Im iPhone wird man nach dem ServerPath gefragt. Den ich mit

http://cal.n0q.org/caldav.php/noqqe/addressbook

Mein Fehler war eben genau die Angabe des Protokolls. Ich meine sorry. Apple probiert hier gefühlte 1,3 mio (nichtmal wirklich RFC spezifizierte) Orte an denen meine Kontakte serverseitig wohl liegen könnten durch und am Ende können die nichtmal ein führendes http:// wegparsen? Egal. Fehler sah wie folgt aus:

http://http//cal.n0q.org/caldav.php/noqqe/addressbook

Macbook

Hier nun der wirklich lustige Teil. Das Address Book des Macbooks. Selbes “Verifying” Spielchen wieder.

Nachdem ich rausgefunden habe wie ich das intuitive Interface der App wirklich benutzen soll kam nur folgendes auf meinem Webserver an:

1
2
77.191.14.156 - - [09/Apr/2012:19:35:53 +0200] "PROPFIND /caldav.php/noqqe/addressbook:0(null)/ HTTP/1.1" 401 401 "-" "Address%20Book/883 CFNetwork/454.12.4 Darwin/10.8.0 (i386) (MacBook2%2C1)"
77.191.14.156 - - [09/Apr/2012:19:35:53 +0200] "PROPFIND /caldav.php/noqqe/addressbook:0(null)/ HTTP/1.1" 400 477 "-" "Address%20Book/883 CFNetwork/454.12.4 Darwin/10.8.0 (i386) (MacBook2%2C1)"

Herzlichen Glückwunsch. Woher kommt dieses “:0(null)” ? Ich habe den Serverport angegeben:

Ich habe mehr als 10 mal versucht das Interface korrekt auszufüllen, aber hatte keine Chance. Nach einmaligem Anlegen konnte ich den Serverpath nicht mehr editieren und wenn ich Ihn von vornherein eingetragen habe bekam ich immer das oben beschriebene “:0(null)”.

Ich hab mir schliesslich die Config von Addressbuch mühsam ergrept und gefunden:

1
~/Library/Application Support/AddressBook/Sources/FC24F051-B1B2-4286-9A28-5830207F0DA2/Configuration.plist

Dort gibt es unter anderem folgende Paramteri (bereits korrigiert):

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
    <key>_className</key>
    <string>PHXCardDAVSource</string>
    <key>disabled</key>
    <integer>0</integer>
    <key>haveWriteAccess</key>
    <integer>0</integer>
    <key>isSharedABAccount</key>
    <integer>1</integer>
    <key>name</key>
    <string>cal.n0q.org</string>
    <key>refreshInterval</key>
    <integer>0</integer>
    <key>serverSupportsSearch</key>
    <integer>0</integer>
    <key>servername</key>
    <string>http://cal.n0q.org:80/caldav.php/noqqe/addressbook</string>
    [...]
</dict>
</plist>

Hurra. Ohne das kaputte Interface kann mein Address Book problemlos mit meinem neuen DaviCal Server reden.

April 01 2012

09:11

ASCII Statistik Graphen mit Bash

Vor einem Jahr hab ich mich mit einem ASCII Balkendiagramm beschäftigt. Als es dann fertig war kams unter dem Namen statistical auf Github: http://github.com/noqqe/statistical

Hab mir überlegt wie schwierig das wohl ist, dass ganze Teil nochmal so umzubauen, dass vertikale Balken entstehen. Horizontal gesehen ist das ja relativ easy. Etwas skalieren hier und da und dann einfach die Anzahl der Zeichen in einer Zeile ausgeben.

Im v-barplot ist da schon etwas mehr Logik nötig. Aber es ging dann trotzdem. Heraus kam dabei folgendes:

./v-barplot foo:24 bar:90 alice:76 flo:32 blu:79 fa:12 bob:230 kika:121

Beide Skripte (v-barplot & h-barplot) sind jetzt im statistical Repo. Anregungen & Kritik immer gerne.

March 23 2012

14:11

The Revival of SCCS

Ich durfte wie bereits erwähnt auf den Chemnitzer LinuxTagen einem Vortrag zur Geschichte von Versionskontrollsystemen und dem Revival von SCCS lauschen. Diesen fand ich unter anderem (besonders beim Historischen) informativ und unterhaltsam.

Nicht übereinstimmen kann ich aber in den angebrachten “Vergleichen” von SCCS zu (unter anderem) git. Die Vortragsfolien können hier angesehen werden.

Die Repository Initalisierung

Initalisierung aller OpenSolaris Source Files:

SCCS: 8 Sekunden
git: 100 Sekunden

Schnelle Massenübernahme in SCCS, SCCS Seite 29

Aus dem Hörsaal kam die berechtigte Frage:

Wie oft mache ich das?

Ich denke das spricht schonmal für sich, aber das eigentliche Feature hierbei ist, dass git von allen Files im Repo einen Binärblob in .git/ ablegt. Während SCCS nur Diffs vom letzten zum neuen Commit speichert.

Das hab ich mal nachgebaut, kommt schon hin:

1
2
3
4
$ time git add .
real  0m38.405s
user  0m17.121s
sys 0m2.620s
1
2
3
4
$ time git commit -a -m "init"
real  0m26.078s
user  0m6.132s
sys 0m1.660s

Nachvollziehbar, dass git länger dafür braucht alle Files zu kopieren als SCCS mit “Ah, hier ist noch ein File, schreib ich den Namen des Files mal in meine Liste”.

Das Datenvolumen

Die angesprochenen Werte auf Seite 36 der Präsentation beziehen sich auf simple Timestamps. Jörg Schilling hat hier 2 Mio. Timestamps erstellt und mit git und sccs jeden davon mit jeweils einem Commit abgeschlossen.

Platzbedarf mit SCCS ca. 300 MB (komprimiert 160 MB)
Platzbedarf mit GIT geschätzt: ca. 15 TB

Dauertest mit SCCS >2 Millionen Deltas, SCCS Seite 36

Ich war so frei das einfach mal (aus zeitlichen Gründen mit 1 Mio. Files) nachzustellen:

1
2
3
4
5
6
7
8
9
#!/bin/bash
touch test 
git add test 
C=0
time while [ $C -le 1004225 ]; do
  date "+%Y%m%d %H%M%s%N" > test 
  git commit -a -m "$C"
  ((C++))
done

Größe nach dem Command:

1
2
$ du -sh /tmp/1miocommits/
12G .

Ich bin mir nicht sicher was Jörg hier genau getan hat. Meine Testwerte unterscheiden sich jedenfalls erheblich von dem, was im Vortrag vorkommt.

Unter anderem wurde erwähnt, dass die Größe des Git Repositories hochgerechnet wurde. Nun das ist natürlich insofern doof, wie man weiss das git Deduplication betreibt. Teile aus den Blobs werden einmalig aufgehoben, wenn sie idientisch sind. So lässt sich viel Platz sparen und das Konstrukt des “Hochrechnens” bricht zusammen. Selbst wenn ich das jetzt nur verdopple kommen dabei 24 GB statt 15 TB raus.

Die Zeit

Ein weiterer Punkt der meines Erachtens beim Vergleich von git zu SCCS außer acht gelassen wurde. Die Zeit.

Was mich sehr interessiert sind die Wiederherstellzeiten. Klar git hat einen spezifischen Commit welcher auf ein Objekt im Hash Store zeigt. Dieser wird ausgelesen und fertig ist die Wiederherstellung.

(Bild von progit.org - Creative Commons Attribution Non Commercial Share Alike 3.0 license)

Aber bei SCCS? Angenommen ich möchte vom 1.000.000 Commit zum 1. zurück. Alle Diffs werden dazu auf das aktuelle File angewandt und zurückgerechnet bis das File wieder am Ursprungszustand angekommen ist. Ob das Spass macht?

Die Konsistenz

Selbes Szenario hier. Ich weiss nicht was passiert wenn das Diff File von SCCS unterwegs mal kaputt geht. Aus welchen Gründen auch immer. HDD Block kaputt oder versehentlich editiert. Faktisch sollte das File dann nicht mehr herstellbar sein.

Bei git bleibt weiterhin der mit zlib komprimierte Binary Blob bestehen und alles ist gut weil wie oben der Commit auf einen binär Blob referenziert. Selbst wenn dazwischen mal ein Block eines Blobs kaputt sein sollte (oder was auch immer).

Ende

Ich möchte zum Schluss nochmal unterstreichen, dass ich in keinster Weise den Vortrag oder die Weiterentwicklung von Jörg Schilling an SCCS kritisieren will. Im Gegenteil. SCCS ist für bestimmte Einsatzzwecke bestimmt nett, eben weil es “anders” ist als git. Aber, dass SCCS in allen Punkte besser als git möchte ich nicht unterschreiben.

March 22 2012

19:16

Chemnitzer Linux Tage 2012

Mittlerweile das 3. Jahr, dass ich mich bei den Chemnitzer Linux Tagen habe blicken lassen. Wie immer war alles sehr super, klasse organisiert (dickes Kompliment an die Orga) und interessant :)

Kurze Review der Vorträge

  • Penetration Testing mit MetaSploit MetaSploit ist angeblich mit 1,2 Mio. Zeilen das größte gepflegte OpenSource Ruby Projekt. Wohl wegen den Zig Plugins :)

  • Der Systemaufruf und was danach passiert Ein bisschen was zu SysCalls unter Linux und Unix. Folien waren leider nur begrenzt lesbar wegen gelber Schrift auf weissem Grund. Ansonsten viel C Beispiele.

  • strace für Bash Versteher strace benutzen um Bash Probleme zu debuggen? Einwandfrei. Manchmal etwas überzogen gleich zu strace zu greifen, aber ansonsten super, da ich bisher wenig mit strace gemacht hatte.

  • Mit OpenStack zur eigenen Cloud Auch nett gewesen. Die verschiedenen Komponenten von OpenStack mal kennenzulernen die von RackSpace und der NASA entwickelt werden.

  • Ursprünge der Versionsverwaltung und Revival von SCCS Den Folien habe ich nichts hinzuzufuegen. Ganz besonders nicht Seite 36. Aber ich habe schon wieder Schaum vorm Mund, wenn ich dran denke. Vielleicht gibts darüber einen separaten Blogpost.

  • Bitcoin, das elektronische Geld Paar interessante Hints bei gewesen. Wenn man sich aber schonmal schlau gelesen hat war wenig neues dabei.

  • LinuXContainer in der Praxis Fand ich persönlich vortragstechnisch und inhaltlich den besten Vortrag. Bin auch schon 2 Stunden am basteln damit, wenn ich schonmal Urlaub habe.

March 08 2012

18:38

Das Ext4 Directory Indexing

Mit ext4 kam unter anderem ein Feature hinzu, welches sich Directory Indexing nennt. Es ist dazu gedacht in Verzeichnissen mit vielen Dateien eine Art Map anzulegen an welchen Inodes welche Files liegen und kommt erst ab Fileanzahl X pro Directory automatisch dazu. Ziel der Entwickler war natürlich Performance Gewinn.

Allerdings kauft man mit diesem Feature auch eine zusätzliche Limitierung mit ein, bei der ich mich schwer tat wirklich (aufgrund in meiner Wahrnehmung mangelnder Berichte und Doku) das Problem zu debuggen.

Die Limitierung bei vielen Files sind in den meisten Fällen erstmal die Inodes der Platte. Ist die Platte aber ausreichend groß (oder die Inodes ausreichend klein) kommt hier das Directory Indexing ins Spiel:

1
EXT4-fs warning (device /dev/sdd): ext4_dx_add_entry: Directory index full!

Rsyncs bzw. Schreibende Zugriffe in das Verzeichnis brechen ab und im dmesg findet man obige Meldung. Problem dabei: In dem Directory Index sind so viele Files gelistet, dass in dem (wahrscheinlich FS Designtechnisch limitierten, korrigiert mich bitte) Hashmap Block kein Platz mehr ist. Es können schlicht und ergreifend keine neuen Einträge hinzugefügt werden.

Was jetzt?

Längeres wälzen von Dokumentation lässt sich nicht vermeiden.

A linear array of directory entries isn’t great for performance, so a new
feature was added to ext3 to provide a faster (but peculiar) balanced tree keyed
off a hash of the directory entry name. If the EXT4_INDEX_FL (0x1000) flag is
set in the inode, this directory uses a hashed btree (htree) to organize and
find directory entries.

Ext4 Disk Layout, ext4.wiki.kernel.org

Oder auch andere schaurige Threads aus Mailinglisten:

http://www.mail-archive.com/cwelug@googlegroups.com/msg01937.html

Mit debugfs lassen sich die Informationen des Filesystems auszulesen, die einen interessieren. Basic Problematik ist einfach, welches Verzeichnis ist betroffen, wie konnte das passieren und wie bekomme ich es wieder heile.

1
2
3
4
5
6
7
8
9
$ cd /var/
$ debugfs
debugfs> open /dev/sdd1
debugfs> cd log/
debugfs> htree .
[...]
Number of Entries (count): 508
Number of Entries (limit): 508
[...]

htree listet die Indexes in dem Ordner und Informationen zum hashed B-Tree. Die Limit und Count Values sprechen denke ich für sich.

Okay. Problem gefunden. Wie beheb ich es?

Man baut den Directory Index neu auf, wobei der alte Dir Index prinzipiell behalten wird und der Neue an der letzten Stelle auf den weiteren Index referenziert.

1
fsck.ext4 -yfD /dev/sdd1

Dazu ist ein unmounten zwingend erforderlich, was bei produktiven Systemen unschön ist. Oder man löscht das Verzeichnis.

Wie sich später herausgestellt hat war die Ursache davon ein nicht korrekt funktionierendes Logrotate welches ca 8 Mio. Files produziert hat. Das Löschen hat auch nur ca. 10 Tage gedauert. Nur so am Rande.

Irritiert.

Zum Abschluss muss ich sagen bin ich etwas.. irritiert. Man schafft ein Feature, dass dann einspringt wenn es viele Files werden (bei meinen Tests ab 300.000 Files), welches dann später wegen diesen vielen Files zu fehlern führt. In dem Bereich dazwischen ist das eventuell wirklich nett zu haben, weil Perfomance. Aber dass ich den “Referenzakt” nicht anstossen kann während das FS gemountet ist finde ich dann speziell für den HA Betrieb von Servern … fragwürdig.

Klar es ist in keinem Fall eine gute Idee mehr als 2 Mio. files in ein Verzeichnis zu legen, aber hey.

Wirklich gestört hat mich eher das mangelhaft Dokumentierte Vorgehen dafür. Seitens Entwickler, seitens Community. Aber deswegen hab ich ja jetzt diesen Post verfasst.

March 05 2012

20:22

Switched to Octopress

Hatte von Octopress gelesen. Dann nochmal im k4cg drüber gesprochen. Irgendwie. So halb und anschliessend für super befunden.

Ich weiss nicht warum, aber irgendwie hat mich das Thema dann einfach nicht mehr los gelassen. Hier probiert, da gemacht. Das Ende vom Lied war dann, dass ich ein fast vollstänidg migriertes Blog in Octopress lokal gebaut hatte. Dann wars auch schon egal und ich hab mein Wordpress eingestampft.

Eigentlich ging alles ganz fix.

  • Ruby 1.9.2 via rvm installiert
  • Die Anleitung auf octopress.org befolgt
  • In Wordpress Inhalte in wordpress.xml exportiert
  • Dem Konvertierungstool exitwp vorgeworfen
  • Alles in source/_posts platziert
  • wordpress.xml nach [Disqus.com] hochgeladen
  • Viele sed/awk Spielchen für die richtigen ImagePfade und Code Block Formattierung betireben
  • Deployed auf Webserver
  • Apache Redirects für alte Posts eingerichtet

Lediglich das umgemappe und durch die Gegend redirecte war müßig. Aber naja. Jetzt ist schön und auch schon umgezogen. Mir gefällts.

Was mir bei der Recherche noch aufgefallen ist:

The <center> element is deprecated in HTML4 since 1998. Just use CSS to make it
or its wrapper a block element with a fixed width and margin: 0 auto

BalusC, Stackoverflow

WTF. Ich habe ca. 7 Jahre danach das erste mal ein Buch gelesen, dass sich mit HTML beschäftigt und es war dort schon deprecated. Das war mir nicht klar.

March 03 2012

noqqe
16:13
if [ $KEYWORDCOUNT -lt 25 ]; then
    alert_page()
fi

So doof sind die nicht :/

January 22 2012

14:09

MySQL | Table Migration zu InnoDB

Ich durfte letztens einer schönen Schulung zum Thema MySQL lauschen. Dabei kam viel herrum. Ein Teil davon hat sich mit verschiedenen Storage Engines beschäftigt.

Ich habe mich entschieden den Großteil meiner Datenbanken zu InnoDB umzuwandeln. Welche Vor- und Nachteile das hatt sollte sich jeder vorher klarmachen. Stichwort: ACID und Fulltext-Search. Natürlich könnte man einfach mit ALTER arbeiten. Aber ich wollte nicht umbedingt die alten MyISAM Tables noch im FS liegen haben. Also alle Datenbanken droppen und den geänderten Dump wieder einspielen, sodass die Tables neu (mit InnoDB) angelegt werden.

Zuersteinmal eine Liste mit den generieren mit den Datenbanken die man Bearbeiten möchte. Es ist zu beachten, dass man den mysql Table selbst nicht auf InnoDB umstellen möchte.

1
mysql -u root -p -e "show databases;" -N --batch | grep -v ^information_schema$ | grep -v ^mysql$

Die Liste der Datenbanken wird nachher noch hilfreich sein. Danach will man wahrscheinlich erstmal alle Dienste beenden, die auf dem MySQL zugreifen (Apache, Tomcat, whatever). In der my.cnf habe ich dann folgende Optionen für die InnoDB spezifiziert.

1
2
3
4
5
6
7
defaulot-storage-engine = InnoDB
innodb_buffer_pool_size = 16M
innodb_additional_mem_pool_size = 2M
innodb_log_file_size = 5M
innodb_log_buffer_size = 8M
innodb_flush_log_at_trx_commit = 1
innodb_lock_wait_timeout = 50

Anschliessend den Dump erstellen und alle ENGINE=MyISAM durch InnoDB ersetzen:

1
2
mysqldump -u root -p > all-databases.sql
sed -i -e 's#ENGINE=MyISAM#ENGINE=InnoDB#g' all-databases.sql

Vorsicht. Hier ist mysql als Datenbank mit gedumped! Mir ist dabei keine wirklich einfache Zeile eingefallen die mit Suche/Ersetze Spielchen mysql ausschliesst. Es gibt bei mysqldump die Option “–ignore-table=” aber auch hier hätte ich jeden mysql Table einzeln nennen müssen. Ich hab die Datenbank dann einfach per hand aus dem Dump herausgelöscht.

Außerdem sollte man seinen Datenbank Dump nach FULLTEXT durchsuchen, da dieser von InnoDB nicht unterstützt wird. In meinem Fall hat es nur ein altes Forum das niemand mehr benutzt betroffen, weshalb ich die Zeile einfach löschen konnte.

1
grep "FULLTEXT" all-databases.sql

Um jetzt alle Datenbanken zu droppen hab ich mir folgende Line gebastelt:

1
for x in $(mysql -u root -phierstehteinpasswort -e "show databases;" -N --batch | grep -v ^information_schema | grep -v ^mysql$) ; do mysql -u root -phierstehteinpasswort -e "drop database $x ; " --batch  ; done

Nach der Bearbeitung kann man den Dump mit der neuen Engine für die Tables wieder einspielen:

1
mysql -u root -p < all-databases.sql
Older posts are this way If this message doesn't go away, click anywhere on the page to continue loading posts.
Could not load more posts
Maybe Soup is currently being updated? I'll try again automatically in a few seconds...
Just a second, loading more posts...
You've reached the end.

Don't be the product, buy the product!

Schweinderl