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

January 22 2012

13: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.

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.

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:

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.

grep "FULLTEXT" all-databases.sql

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

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:

mysql -u root -p < all-databases.sql

January 08 2012

12:47

GNU Parallel

Vom GNU Parallel Projekt habe ich vor einiger Zeit in der Arbeit so am Rande etwas mitbekommen. Nachdem ich mir die gute Dokumentation etwas angeschaut habe, hab ich Lust bekommen das mal selbst auszuprobieren.

Ich dachte es wäre eine gute Idee einfach ein paar md5 Summen zu bilden.

$ time seq 1 10000 | parallel 'echo {}| md5sum &> /dev/null '
real 0m20.102s
user 0m35.082s
sys 0m24.918s

Nun. Ich bilde nicht so oft 10.000 md5 Summen. War das jetzt viel? Oder wenig? Um einen Vergleichswert zu haben sollte ich wohl auch mal nachsehen, wie das ohne Parallel so aussieht.

$ time for x in $(seq 1 10000); do echo $x | md5sum &> /dev/null; done
real 0m13.504s
user 0m2.368s
sys 0m3.948s

Ziemlich seltsam. Obwohl ich 10.000 md5 Summen gebildet habe war die sequenzielle Methode schneller als die Parallele. Zumindest dachte ich zu dem Punkt noch das es seltsam ist. Aber an was lag das. Ich hab mir dann überlegt ob ich nicht vielleicht doch noch eine andere Aufgabe als md5 Summenbildung abbilden sollte. Ich entschied mich dazu 1000 mal eine 100.000 Zeichen lange Zeichenkette durch gzip zu schubsen.

$ time seq 1 1000 | parallel 'cat /dev/urandom | head -c 100000 | gzip &> /dev/null'
real 0m7.845s
user 0m4.064s
sys 0m20.485s

7 Sekunden. Sieht eigentlich ganz nett aus. Und in der Schleife sequenziell?

$ time for x in $(seq 1 1000); do cat /dev/urandom | head -c 100000 | gzip &> /dev/null; done
real 0m31.869s
user 0m8.301s
sys 0m33.658s

Okay. Jetzt weiss ich, das GNU Parallel eher was für (rechen-)intensivere Aufgaben ist als für viele kleine Prozesse. Anscheinend braucht das Parsing des zusätzlichen Binaries doch etwas zu lange um einen Prozess zu ordnen der sowieso nach sehr kurzer Zeit wieder beendet ist. Alles in allem gefällt mir GNU Parallel aber sehr gut wenn man weiss für was man es einsetzen muss :)

December 11 2011

18:45

fbcmd | Nie wieder Geburtstage vergessen via Shell.

Die nachfolgende Beschreibung eines technischen Vorgangs würde die Mehrheit der Gesellschaft wahrscheinlich als soziologisch fragwürdig abstempeln. Jedoch beschreibe ich den Hergang trotzdem und gerade deswegen.

Ich weiß gar nicht mehr wie genau ich auf fbcmd gekommen bin.  Im Zweifel über einen XML basierten Medienkanal. Jedenfalls ist fbcmd ein äußerst schönes Tool um die gängigen Informationen zum eigenen Facebook Account auf der Kommandozeile abzufragen. Dazu bietet es wahnsinnig trickreiche Queries und “Vergruppungen” der Facebook Bekanntschaften. Alles dazu hier und besonders hier.

Somit lässt sich wunderbar ein automatisches “Alles Gute zum Geburtstag!” bauen. Vorraussetzung ist hierfür eine funktionierende Installation von fbcmd.

Der von fbcmd vorgeschlagene Query um eine Geburstagsnachricht an die Pinnwand von jenen zu senden, deren Geburtstag sich heute jährt lautet:

fbcmd WALLPOST =bday 'Alles Gute zum Geburstag!'

Das lässt sich natürlich wunderbar in einen Cronjob verbauen, der einmal täglich um 15:00 eben diesen Query ausführt:

0 15 * * * fbcmd WALLPOST =bday 'Alles Gute zum Geburstag!' > /dev/null

Weil ich aber wissen möchte, wem mein Rechner alles in meinem Namen zum Geburtstag graturliert hab ich das noch leicht modifiziert und lasse mich via Mail darüber benachrichtigen:

0 15 * * * fbcmd WALLPOST =bday 'Alles Gute zum Geburstag!' | grep -v "^No Friends With Birthday Matches$" | mail -s "fbcmd Gratulation" user@domain.de

Eigentlich ist der Titel des Posts gar nicht richtig. Man vergisst Sie trotzdem. Aber ein Device erledigt die Arbeit für einen :)

November 26 2011

12:53

Loading | Eine Bash-Progress-Bar

Für ein kleines Projekt, an dem ich so nebenher immer etwas schreibe habe ich eine Art Ladebalken gebraucht. Habe ein paar wirklich coole Lösungsansätze gefunden, aber es läuft meistens auf Depencies raus (pv z.B.) oder nicht wirklich mein Anwendungsfall.

Ich hab mir dann kurzerhand was selber gebastelt. Ich gebe zu ich hätte es auch so gestaltet können das es einfach nur für meinen Use-Case gereicht hätte, aber das erschien mir unsinnig. Wenn ich mich schon einen halben Abend hinsetze, dann können ja evtl. auch mehr Menschen was davon haben. So entstand dann die bash-progress-bar.

Zu allererst besteht der Ladebalken aus einer while true Schleife. Sollte die Bar in ein Skript einbaut werden wäre die Bedingung dem Skript anzupassen. Ob das jetzt ein test -e auf ein File ist das getouched wird oder eine Art Counter bleibt jedem selbst überlassen.

$ git clone git://github.com/noqqe/bash-progress-bar.git
$ cd /bash-progress-bar/
$ ./loading.sh
> [            #####       ]

Alle Parameter sind natürlich anpassbar. Ich habe versucht so gut wie alles anpassbar zu halten. Ich hoffe das ist mir gelungen ;)
./loading.sh Groesse Geschwindigkeit Rahmen-Anfang Füllcharacter Rahmen-Ende
./loading.sh 50 0.02 [ "######" ]

Ohne irgendwie ein GIF-File zu erstellen kann ich das jetzt leider schlecht im Blog demonstrieren. Deshalb: ausprobieren :) Mehr Infos auf der Github Page.

Fragen, Anregungen, Kritik erwünscht!

October 02 2011

21:58

Statistiken | Einfache Graphen mit R und MySQL Anbindung

Immer mal wieder reizt mich die Programmiersprache für Statistiken R. Um diesen Reiz dann auszuleben hab ich vor ein paar Monaten angefangen kleine Graphen für den zufallsbasierten Simulator ZRE zu bauen. Das Spiel “läuft” einfach 24/7 und schreibt für jedes geschehene Event Einträge in die Datenbank. Diese Einträge werte ich dann mit Hilfe von R aus.

Dazu gibt es ein Skript. Nämlich zre.R (Ob das die Konvention bei R-Skriptnamen ist, kann ich nicht sagen ;) )

#!/usr/bin/env Rscript

### General R-Script
# MySQL
library(RMySQL)
con <- dbConnect(MySQL(), user="", password="", host="", client.flag=CLIENT_MULTI_RESULTS)
# Style
zre_colors <- colors()[grep("green",colors())]
zre_mint <- colors()[c(48,86,50)]

Im Klartext wird aus dem CRAN Library Verzeichnis die Library RMySQL includiert und die Verbindung in der Variable con abgelegt. Ähnlich wie bei PHP. Für alle Debian / Ubuntu Benutzer empfiehlt sich aber, die Library einfach über das Paketsystem nachzuinstallieren.

$ aptitude install r-cran-rmysql

Standardmäßig sehen Graphen die mit R erstellt werden ziemlich mau aus. Die weiteren Variablen unter Style habe ich gewählt um mir die Colorierung der Graphen etwas zu erleichtern. Diese werden später einfach als Attribute in den Plots/Barplots gesetzt und ausgewertet. Ich fange einfach mal der Reihe nach an:

Die Abfolge ist immer ziemlich ähnlich. Zu aller Erst wird der Query für die Datenbank an die Variable sql übergeben. Diese Variable wiederrum wird zusammen mit der Connection an die Funktion dbGetQuery übergeben und das Ergebnis dessen schliesslich in zre_wins gespeichert. Anschliessend ein paar kleine Informationen an das Dateiformat übergeben und den Graphen bauen.

Die Funktion par lässt sich erstmal als eine Art Environment Funktion für Graphen verstehen. Hier werden Eigenschaften wie Schriftfarbe, Hintergrund, Axenfarbe, und Liniendicke definiert. Danach kommt (wie ich finde) der schwierigste Teil. Bauen des Graphen. Je nach Art des Graphen (Balken, Linien, Torte u.ä.) werden logischerweise verschiedene Parameter erwartet. Die Daten werden hierbei jetzt als Matrix an ein Balkendiagram übergeben. Weitere Informationen wie die Überschrift (main) und die Beschreibung der Balken (names.arg) werden einfach angefügt.

# Graph: Wins

sql <- paste("SELECT COUNT(id) AS sum, side FROM zombies.zre_wins GROUP BY side;")
zre_wins <- dbGetQuery(con, sql)
png(file="wins.png", width=400, height=400)
par(col="white", bg="transparent", col.axis="white", col.lab="white", col.main="white", lwd=2)
barplot(as.matrix(zre_wins$sum), main="Game Summary", names.arg=c(zre_wins$side), beside=TRUE, col=zre_mint)

Selbes Spiel wieder, nur mit mehr Balken und anderem Use-Case. Diesmal werden die 25 Konflikte mit den meisten Opfern visualisiert.

# Graph: Highest Kills

sql <- paste("SELECT id, kills FROM zombies.zre_kills ORDER BY kills DESC LIMIT 25;")
zre_matches_highest <- dbGetQuery(con,sql)
png(file="highestkills.png", width = 400, height = 400, bg="transparent")
par(col="white", bg="transparent", col.axis="white", col.lab="white", col.main="white", lwd=4)
barplot(zre_matches_highest$kills, zre_matches_highest$id, main="25 Highest Kills", beside = TRUE, ylab="Kills", col=zre_colors)

Aber da Balkendiagramme auch irgendwann Langweilig werden geht das natürlich auch anders. Die 25 letzten Konflikte werden im “Opferverlauf” wie folgt dargestellt:

# Graph: Kills

sql <- paste("SELECT kills FROM zombies.zre_kills ORDER BY id DESC limit 25;")
zre_kills <- dbGetQuery(con,sql)
yrange <- range(zre_kills$kills)
xrange <- length(zre_kills$kills)
png(file="kills.png", width=400, height=400, bg="transparent")
par(col="white", bg="transparent", col.axis="white", col.lab="white", col.main="white", lwd=4)
plot(zre_kills$kills, xlab="Games", type="b", ylab="Kills", main="Kills from last 25 Attacks", col=zre_mint)

Damit es nicht immer nur um Tote geht, auch mal was erfreuliches. Die Geburtenrate in ZRE steigt! :)

# Graph: BirthRate

sql <- paste("SELECT Month(date) AS month, count(id) AS born FROM (SELECT *, Month(date) AS M FROM zombies.zre_born) t Group by M; ")
zre_birthrate <- dbGetQuery(con,sql)
png(file="birthrate.png", width=400, height=400)
par(col="white", bg="transparent", col.axis="white", col.lab="white", col.main="white", lwd=3)
barplot(zre_birthrate$born, xlab="Month", ylab="Born Humans/Zombies", names.arg=c(zre_birthrate$month),main="BirthRate per Month", col=zre_colors)

Und auch das Wetter soll bei der ganzen Sache nicht zu kurz kommen. Hierbei bitte besonderes Augenmerk auf die Legende rechts oben. Eine direkte Zuordnung der Werte und Farben ist nicht nötig, da die Farben in der selben Reihenfolge von zre_colors befüllt werden wie die Balken. Die erschreckend hohe Zahl an Naturkatastrophen erklärt das aber trotzdem nicht :)

# Graph: Weather
sql <- paste("SELECT COUNT(id) AS count, weather FROM zombies.zre_weather GROUP BY weather ORDER BY count DESC;")
zre_weather <- dbGetQuery(con,sql)
png(file="weather.png", width=400, height=400)
par(col="white", bg="transparent", col.axis="white", col.lab="white", col.main="white", lwd=2)
barplot(zre_weather[,1], main="Weather in ZRE", beside = TRUE, col=zre_colors)
legend( 5, 40000, zre_weather$weather, cex=0.9, fill=zre_colors, col="white")

Das volle zre.R Skript befindet sich wie das meiste auf Github: https://gist.github.com/1031260

August 27 2011

11:10

Arduino | Ich baute ein Megabitmeter

Vor einiger Zeit hab ich über den Podcast von Tim Pritlove (NSFW) von dem Projekt MegabitMeter erfahren. Es hat mich ehrlichgesagt fasziniert. Der eigentliche (im Namen implimzierte) Zweck zwar weniger, aber gernerell einfach Werte über ein USB Device darstellen zu können. Genaue Anwendungsfälle gibts weiter unten.

Zunächstmal hab ich mich ausgiebig mit dem HowTo beschäftigt welches ich (bis auf ein paar Stellen) sehr gut finde. Die letzten Paar Unstimmigkeiten habe ich dann mit dem wirklich netten und zuvorkommenden Betreibern des Projekts via Mail abstimmen dürfen :) Das lag aber auch an meinen fehlenden elektrotechnischen Kenntnissen.

Ich muss dazu sagen, dass ich in der glücklichen Situation war und jemanden kannte, der in einer Firma tätig ist, die solche Messgeräte anfertigt wodurch ich keinen Kit kaufen musste. Das ist auch der Grund warum das Messgerät etwas anders aussieht.

Ich denke auch das der Sinn des Projekts eher das “do-it-yourself” ist und der wirtschaftliche Erfolg nur eine positiver Nebeneffekt der Betreiber ist… (Zumindest hoffe ich, dass ich das nicht falsch interpretiert habe). Außerdem schwierig war, dass der Kit 2 (incl. dem Arduino) nicht verfügbar war, da laut Twitter gerade keine Arduinio Nano in rauen Mengen billig einzukaufen sind. Den Arduino Prozessor habe ich deswegen von TinkerSoup.de geordert.

Wenn alles fertig gebastelt ist, kann man dem Gerät einfach via echo Werte übergeben.

$ echo "200" > /dev/ttyUSB0

Ein paar Anwendungsbeispeile:

Zufällige Zahlen auf das Gerät projezieren
while true; do RND=$(($RANDOM % 99 * 10)); printf "$RND\n" > /dev/ttyUSB0 ;echo $RND; sleep 2 ; done

Zombie Kill Meter (In Verbindung zu zombies.n0q.org)
while true ; do mysql -u user -ppw -e \"SELECT kills from zombies.zre_kills ORDER BY id DESC LIMIT 1;\" | grep -v ^kills ; sleep 3; done" > /dev/ttyUSB0

Port 80 Verbindungen des Webservers
ssh user@host "while true; do echo \$(( $(netstat -tapn | grep -c -e ':80\s*') * 100 )) ; sleep 2; done" > /dev/ttyUSB0

An weiteren Snippets bastle ich im Moment noch. Werden eventuell nachgereicht wenn Sie spruchreif sind. Am Ende noch ein riesen Danke für die Software und die Projektidee sowie das wunderbare HowTo an das Team von <a href=”megabitmeter.de”>megabitmeter.de</a>

August 13 2011

12:03

ROT13 Verschlüsselung in Bash

Seit ich meinen neuen Arbeitsweg antrete und täglich ca eine Stunde im Zug verbringe, höre ich umso mehr Podcasts. Besonders gut finde ich http://ulm.ccc.de/dev/radio/. Es ging unter anderem um Algorithmen und Kryptologie im Allgemeinen. Unter anderem eben auch die ROT13 Verschlüsselung.

Grafik aus Wikipedia unter Public Domain

Ich habe mir überlegt wie schwierig es wohl sein kann, diesen in Bash zu implementieren. Nach kurzem googlen findet man immer wieder eine kleine wirklich ausgefuchste, trickreiche Zeile:

$ tr A-Za-z N-ZA-Mn-za-m

Irgendwie war mir das aber zu langweilig, mir die Arbeit von einem vorgefertigten Binary erledigen zu lassen. Ich wollte es in echtem Bash selbst schreiben. Was ich dann auch getan habe.

Usage:

$ ./rot13 "hello world"
uryyb jbeyq

$ echo "hello world" | ./rot13
uryyb jbeyq

# Verschlüsseln und entschlüsseln hintereinander.
$ echo "hello world" | ./rot13 | ./rot13
hello world

# Zeichentabelle anzeigen
$ ./rot13 -t

Sollten Zeichen vorkommen, die sicht nicht im Table befinden, werden diese automatisch erkannt und bleiben unverschlüsselt.

$ ./rot13 "Ich wollte nur [...] und dann ist das Universum explodiert."
Ipu jbyygr ahe [...] haq qnaa vfg qnf Uavirefhz rkcybqvreg.

Genau genommen ist es sogar mehr als nur ROT13. Mit wachsendem Zeichen-Table wächst auch automatisch die Verschiebung der Stellen mit. Es ist also möglich einen eigens definierten Table mit Zeichen anzulegen und diesen zu nutzen. Einzige Bedingung: Es muss eine gerade Anzahl von Zeichen sein.

Und zum Schluss: Danke an /dev/radio für die erhebliche Verkürzung meiner Zugfahrten :)

July 04 2011

18:42

Minecraft + Git + Bash =

Seit mittlerweile erstaunlich langer Zeit spiele ich Minecraft. Minecraft hält seine Daten in ~/.minecraft vor. Also Levels, Statistiken, Items. Das Minecraft Home Directory unter Versionskontolle zu stellen hat unter Umständen mehrere Vorteile, die ich hier kurz erläutern möchte :)

Initiales Setup

Als erstes muss das Verzeichnis initial eingerichtet werden. Initialisierung, hinzufügen aller Dateien und ersten Commit erstellen.

$ cd $HOME/.minecraft
$ git init
$ git add .
$ git commit -a -m "Initialer Commit"

Spielstände manuell Laden und Verwalten (Commits)

Einer der gravierendsten Vorteile. Wer wie ich oft an Klippen hinunter stürzt oder an einem (oder auch mehreren :P ) Creeper(n) scheitert wird das bestätigen können. Einmal gefallen/gestorben gibt es kein zurück mehr. Bis jetzt.

Die hypothetische “Herausforderung” scheint sich gerade aufzutun. Ob jetzt Creeper, Berg oder sonst was ist erstmal egal. Könnte auf jeden Fall kritisch für meinen Minecraft Character enden.

$ git commit -a -m "Ob man den Sprung ueberlebt?"

Nach einem kurzen Tab in die Konsole, sollte das Spiel erstmal gesichert sein und ich kann den Sprung wagen.

Anscheinend überlebt man nicht, aber genau das war auch der kritische Punkt. Genau jetzt bin ich in der Lage meinen alten Spielstand wiederherzustellen. Mit nachfolgendem Kommando verwerfe ich alle seit dem letzten Commit entstandenen Änderungen an meinem Spielstand. Vorher dringend aufs Minecraft Titelmenü zurückkehren!

$ git stash

Dieses Szenario lässt sich nicht nur auf gerade geschehene Ereignisse abbilden sondern auch zwischen Commits die längere Zeit her sind. Wenn nach einer halben Stunde/einem Monat klar wird, das der Minecraft Char gerade nur Müll verzapft hat, kann auch zwischen mehrere Commits hin und her gesprungen werden. Mit welchen git Kommandos das bewerkstelligt wird, bleibt jedem selbst überlassen.

git-revert macht den letzten Commit rückgängig, erstellt dabei einen neuen in dem die Änderungen enthalten sind. Das ist in soweit gefährlich, dass zwischenliegende Commits unberührt bleiben und eventuell in einen großen Haufen Datenmüll zerfallen(!). Eher Anwendung für den “Warp” an einen früheren Zeitpunkt X findet daher git-reset.

$ git reset 66a2594
# oder
$ git reset HEAD^

Das Working Directory wird damit auf einen Stand gebracht, wie es zum Zeitpunkt des angegebenen Commits aussah. Dieser kann somit auch weiter in der Vergangenheit liegen.

Automatische Speicherung (Bash-Einzeiler)

Allerdings muss ich zugeben, dass diese Praxis relativ schnell aufwendig wird. Immer zwischen Fenstern hin und her zappen ist ja auf Dauer auch eher zermürbend. Daher habe ich mir diese “Arbeit” von einer kleinen Bash Zeile abnehmen lassen.

$ SEKUNDEN=10 ; while true ; do git add . ; git commit -a -m "AutoSave $(date)" ; sleep $SEKUNDEN ; done

Ich denke es ist Geschmacksache wie oft bzw. in welcher Frequenz die Commits abgesetzt werden können. Bis jetzt bin ich mit ca 300 Sekunden (5 Minuten) am besten Gefahren. Die Commits rieseln vor sich hin und beeinträchtigen so in keinster Weise den Spielfluss.

[master bf9dd85] AutoSave Mo 4. Jul 19:56:17 CEST 2011
4 files changed, 15 insertions(+), 12 deletions(-)
rewrite saves/0pen_Running/level.dat (100%)
rewrite saves/0pen_Running/level.dat_old (100%)
[master 5ddedc8] AutoSave Mo 4. Jul 19:56:27 CEST 2011
4 files changed, 17 insertions(+), 19 deletions(-)
rewrite saves/0pen_Running/level.dat (100%)
rewrite saves/0pen_Running/level.dat_old (100%)
[master 2d33023] AutoSave Mo 4. Jul 19:56:37 CEST 2011
4 files changed, 10 insertions(+), 11 deletions(-)
rewrite saves/0pen_Running/level.dat (100%)
rewrite saves/0pen_Running/level.dat_old (100%)

Parallele Welten (Branches)

Um einfach mal ein Anwendungsbeispiel zu nennen: Wer in seinem virtuellen Minecraft-Keller mal raue Mengen an TNT gebunkert hat, möchte es nach Möglichkeit auch mal benutzen, right? Aber danach das ganze Dorf wieder aufbauen? Nee… Branching!

Das ist der Punkt an dem die Geschichte der lokalen Minecraft Map sich in zwei Teile spaltet. In einer wird das eigene Bauwerk Sorum und Gumorra mäßig untergehen und in der anderen weiterhin existierenden Welt tollen sich Pigs und Sheeps in Minecarts herum. Die Abzweigung lässt sich wie folgt bewerkstelligen.

$ git branch blowup
$ git checkout blowup

Jetzt kann man in aller Seelen Ruhe TNT verteilen und auch mal Destroyer statt Builder spielen. Tipp: Commit vor der Sprengung setzen :P Explosion immer und immer wieder von vorne genießen ;) Bemerkenswert sind außerdem die unterschiedlichen Abläufe von ein und der selben Explosion, aber dazu vielleicht wann anders ein Blogpost. Irgendwann wird aber auch das dann zur Routine und man wechselt via

$ git checkout master

wieder zu den Schäfchen. Der Branch “blowup” bleibt aber bestehen und lässt sich auch nach weiteren Spielständen immer wieder herbeirufen. Ich habe mittlerweile eine Art Branchset meiner “Lieblingssituationen” im Game, die ich immer wieder durchspielen kann, wie es mir gerade gefällt. Und nein es sind nicht immer nur Explosionen :)

Networking, Baby! (Remotes)

Mein Minecraft Setup mit allen Einstellungen und Spielständen zentral an einem Ort zu haben war ehrlich gesagt meine erste Motivation git einzusetzen. Ich spiele Minecraft auf 3 verschiedenen Maschinen (Ubuntu, Debian und sogar Mac OSX) und wollte keine 3 unterschiedlichen Maps pflegen müssen. Deshalb fing ich an auf meinem Server zwischen zu lagern. Ein eigens laufender git-Server ist hier aber Vorraussetzung! Freies Hosting bei beispielsweise Github fällt wegen der großen Datenmengen (ca. 300MB bei mir derzeit) und der fehlenden Privatsphäre flach. Remote-Server hinterlegen und aktuellen Stand pushen:

$ git remote add origin git@gitserver.com:minecraft
$ git push origin master

Remote-Server auf anderen hosts klonen:

# Ubuntu/Debian
$ git clone git@gitserver.com:minecraft $HOME/.minecraft
# Mac OSX
$ git clone git@gitserver.com:minecraft $HOME/Library/Application\ Support/minecraft

At least

Ich möchte nicht sagen, dass dies hier der ultimative Weg zum heiligen Gral in Minecraft ist. Manchmal weckt eben diese erzeugte “Sicherheit” durch den Reset eine gewisse “Wayne…” Einstellung in einem, die dem Spielspaß ein Kleinwenig den kitzel raubt. Gerade am Anfang hat es mir aber extrem geholfen, nicht bei jedem Wipe alle Items zu verlieren oder sich nach einem Ausflug in den Wald wieder “zurück warpen” zu können.

Auf weitere Ideen im Umgang mit Minecraft und Git freue ich mich natürlich wie immer :)

June 12 2011

11:09

BitCoin | Debian Daemon Script für poclbm-mod

Man muss Dinge über Hirnschäden von Menschen lesen die Nachts guten Gewissens neben einem 4 Grafikarten im SLI-Verbund schlafen und zugleich die Bedenken von sinnierenden Typen die an den Limitierungen von 21 Billionen maximal möglichen BitCoins zweifeln. Umweltverschmutzung ist natürlich auch ein Thema. Klar. Gerechtfertigter Weise.

Wenn Ihr mich fragt, schiesst die BitCoin Mining Gesellschaft am Ziel vorbei. Separate Rechner betreiben schiesst am Ziel vorbei. Hunderte von Euros für neue Grafikkarten ausgeben um 5 MegaHashes/s mehr rechnen zu können schiesst am Ziel vorbei. Euro’s für BitCoins bezahlen schiesst sowieso am Ziel vorbei. Man kann BitCoins meines Erachtens auch benutzen ohne Kopfstände zu machen. Immer wenn der Rechner sowieso gerade läuft, mit der Hardware die man zur Verfügung hat.

Aus diesem Grund habe ich ein kleines Skript gebastelt. Einen Start-Stop-Daemon für /etc/init.d/. Es startet automatisch wenn mein Rechner hochfährt und hört auf wenn ich Ihn herunterfahre. Ganz einfach

$ wget -O /etc/init.d/bitcoin https://gist.github.com/raw/1007794/bitcoin.sh
$ chmod +x /etc/init.d/bitcoin
$ update-rc.d bitcoin defaults

https://gist.github.com/1007794

Ich möchte aber dazu sagen, dass ich dies Funktionstüchtigkeit des Skripts nicht auf anderen Rechnern/Betriebssystemen getestet habe. Vor Benutzung also bitte lesen, verstehen ggf. anpassen. Außerdem wird ein Account bei einem Mining Pool benötigt und der Mining Client an sich (poclbm-mod). Während ich diesen Post geschrieben habe, hat mein BitCoin Mining Client entspannt auf meiner Geforce 8600 GS mit nahezu niedlichen 950 KiloHashes/s vor sich hin gemined.

April 20 2011

10:14

Commandline Tools | PDFs zusammenführen

Aufgrund meiner aktuell vorherrschenden Bewerbungsphase wollte ich ein paar PDF Dateien (hauptsächlich Zertifikate und Zeugnisse) in eine PDF Datei zusammenführen. Auf der Suche nach einem derartigen Programm liefen mir natürlich allerlei (dem anschein nach) hübsche Windows Tools für diese Aufgabe über den Weg. Wie schon oft, fand ich dann aber im Unixboard meine Antwort.

Das Commandline Tool pdftk. Wunderbar für Debian und Ubuntu paketiert.

$ sudo aptitude install pdftk

Ich muss trotzdem zugeben, dass die Syntax mir etwas ungewöhnlich erschien, aber nicht unbezwingbar ist :) Nach ein paar Blicken in die Manpage, kam ich auch da an wo ich wollte.

$ pdftk novell-cert.pdf ripe.pdf lpic-1.pdf cisco-ccna1.pdf cat output Zertifikate.pdf
  \___/ \________________________________________________/  \_/ \____________________/
    |                            |                           |             |
    |                            |                           |             \- Ausgabe an
    |                            |                           |                Zertifikate.pdf
    |                            |                           |
    |                            |                           \- Ausgabe der PDFs
    |                            |
    |                            \- Angabe aller zu kombinierenden PDFs
    |
    \- Programmaufruf

February 07 2011

16:04

DuckDuckGo | Suche via Firefox Addressleiste umstellen

Seit einiger Zeit benutze ich die Suchmaschine duckduckgo.com . Wenn man von dem völlig bescheuerten Namen und dem Logo mal absieht, versteckt sich dahinter eine wunderbare Suchmaschine. Dazu gehört alles was der typische Paranoia Geek so braucht.

Allem vorran die !Bang Suche, die ich mit der Zeit sehr zu schätzen gelernt habe. Jede große Site hat ein Kürzel, mit der Sie durchsucht werden kann. Zum Beispiel “!wiki Alan Turing“. Außerdem geben Sie an, die Suchanfragen nicht zu loggen (http://donttrack.us/), Shortcuts, sowas wie eine Syntax und Wolfram Alpha implementiert zu haben. Alles was DuckDuckGo zu bieten hat unter: http://duckduckgo.com/goodies.html

Um jetzt zum Punkt zu kommen: Meine Standardsuchleiste habe ich via Plugin schon auf Duckduckgo umgestellt. Ich habe aber die blöde Angewohnheit meine Suchanfrage einfach direkt in die Suchleiste des Firefox zu schreiben. Bisher wurde mir das immer brav von Google beantwortet. Ich dachte mit der Installation des Plugins von DuckDuckGo wäre das auch umgestellt. Dem ist aber nicht so. Leider.

Stattdessen gilt es, noch folgende Anpassungen zu machen:

  • about:config in die Adresszeile tippen
  • Nach dem Begriff “keyword.URL” suchen
  • Das Feld doppelklicken (standardmäßig dürfte es leer sein)
  • http://duckduckgo.com/?q=” als String einfügen

Anschließend Firefox Neustart. Nein ich habe kein Geld für diesen Post bekommen. Schon wieder nicht.

February 04 2011

10:18

Statistiken | Using R – The Nerd Way

Momentan interessiere ich mich für R. Die Programmiersprache für Statistiken genießt aktuell ziemliche Popularität.

Persönlich habe ich (in der kurzen Zeit, seitdem ich es benutze und kenne) R als eine Sprache kennengelernt, die nur begrenzt für coole Sachen benutzt wird. Kann an meiner Deklaration von “cool” liegen oder das sich die coolen Sachen bisher meiner Kenntnis entzogen. Aber mal davon abgesehen dass Statistiken immer interessant sind, wird R anscheinend meistens von irgendwelchen Sales-Druiden oder Marketing-Dudes verwendet, die Daten aus der DB ihres Online-Shops kratzen lassen um festzustellen wie viele Rosa Einhörner letzten Monat verkauft worden sind.

Nunja, sagen wirs so. Ich hab überlegt für was ich R nutzen würde und etwas damit gespielt. Prinzipiell ist die vorgehensweise sehr einfach. Ich hab irgendwo ein LogFile o.ä. rumliegen (sozusagen die Rohdaten) und bringe diese mit ein bisschen Bash/Shell Zauber in ein Format welches ich R vorschmeissen kann. R unterstützt… naja so ziemlich alles, was einen halbwegs anständigen Delimiter vorweisen kann.

R arbeitet in diesem Fall mit einer Interaktiven Shell, die die Eingaben interpretiert.
( $: Bash Shell. >: R Shell)

Tweetstatistik meiner Timeline analysieren (via twidge)

# Letzte 200 Tweets ausgeben
$ twidge lsrecent --all > tweets
# Usernamen sortieren und Tweets zählen
$ grep '^<' tweets | awk '{print $1}' | sort | uniq -c | sort -rn
# In R Shell wechseln
$ R
# Twitter Timeline einlesen
> twittertimeline <- read.table("twitter/tweets", head=T, sep="" )
# Kuchenansicht erstellen
> pie(twittertimeline$Tweets, label=twittertimeline$User)

An dieser Stelle kann es passieren, dass es bei zu vielen Daten wirklich sehr unübersichtlich wird. Was genau ich da falsch mache ist mir allerdings etwas schleierhaft. An der Skalierung lässt sich sicher noch arbeiten. Aber mit einem kleineren Satz von Daten, sieht es schon besser aus.
# 20 meisten Twitterer heraussuchen
$ grep '^<' tweets | awk '{print $1}' | sort | uniq -c | sort -n | tail -20 > tweets-20
# Einlesen
> twittertimeline20 <- read.table("twitter/tweets-20", head=T, sep="")
# Balkendiagram erstellen
> barplot(as.matrix(twittertimeline20$Tweets), main="Timeline", ylab="Tweets", xlab="Users", beside=TRUE, col=rainbow(20))

Und damit das ganze auch was aussagt, kann man sogar eine kleine Legende anfügen.

> legend( 1, 60,twittertimeline20$User, cex=0.6, fill=rainbow(20))

History der Bash visualisieren
Wer auf Kuchen steht, kann auch eifnach mal seine Bash History einlesen.
# Command sortieren und zählen
$ history | awk '{print $4}' | sort | uniq -c | sort -rn | head > sys/history
Used Command
1106 ls
889 vim
490 cd
423 git
116 screen
116 rm
81 ./tismc.bash
76 ps
75 less
72 ./coming-home.bash
# Das generierte File in R einlesen
> history <- read.table("sys/history", head=T, sep="")
# Aus dem Object history ein neues Object für Labels erstellen
# in denen die prozentualen Werte der Commands stehen
> history_labels <- paste(history$Command , " " , round(history$Used/sum(history$Used) * 100, 1) , "%", sep="")
# Object und Labels zu einem Kuchendiagramm formen
> pie(history$Used, main="Commands", label=history_labels, cex=0.8)
 

Mailadressen aus mail.log
Um noch ein 3. mal den Anwendungsbereich zu wechseln, kann man damit auch wunderbar das mail.log seines Mailservers unter die Lupe nehmen.

> mailaddresses <- read.table("mail/mail_addresses", head=T, sep="")
> pie(mailaddresses$Mails, main="Mail Adressen", col=rainbow(length(mailaddresses$Address) ), label=mailaddresses$Address)

Egal, mein BWL Lehrer sagte immer: Traue nie einer Statistik, die du nicht selbst gefälscht hast.

December 14 2010

14:33

Bash | Backup eines Files mit Zeitstempel in unkompliziert.

Auf eine besondere kleine Funktion möchte ich kurz aufmerksam machen, weil sie viele Administratoren oder Sonst-Wie-Konfigurationen-vornehmende-Benutzer wahrscheinlich auch brauchen könnten:

buf () { filename=$1; filetime=$(date +%Y%m%d_%H%M%S); cp ${filename} ${filename}_${filetime}; }

Man spielt an der main.cf des Postfix herum oder bastelt an der xorg.conf. Und wie man das eben von dem erfahrenen Linux-Benutzer seines Vertrauens (oder dem UbuntuUsersWiki) gelernt hat, sichert man vorher die Konfigurationsdatei mit dem obligatorischen:

cp xorg.conf xorg.conf.bak

Je nach Intensität der Anpassungen häufen sich auch Backupfiles a la “xorg.conf.bak.bak” oder “.bak2 bis .bak5000″

Fügt man die obige Funktion in seine .bashrc hinzu, erledigt sich das Thema relativ schnell.

buf xorg.conf

Erstellt automatisch ein File mit dem aktuellen Zeitstempel im aktuellen Verzeichnis. Nochmal im formatierten Zustand:

buf () {
filename=$1
filetime=$(date +%Y%m%d_%H%M%S)
cp ${filename} ${filename}_${filetime}
}

Dass commandlinefu.com eine großartige Site ist, ist wahrscheinlich für die meisten nichts Neues. Teileweise regnet es dort wunderschöne kleine Kommandozeilen für den Alltag.

September 26 2010

12:56

Bash | Futurama Zitate aus slashdot.org HTTP-Header auslesen

Bin heute morgen über ein Easter-Egg von Slashdot.org gestolpert. HTTP-Header:

$ curl -Is slashdot.org
HTTP/1.1 200 OK
Server: Apache/1.3.41 (Unix) mod_perl/1.31-rc4
SLASH_LOG_DATA: shtml
X-Powered-By: Slash 2.005001
X-Fry: You'll barely regret this.
X-XRDS-Location: http://slashdot.org/slashdot.xrds
Cache-Control: no-cache
[...]

Bei so ziemlich jeder Anfrage steht an der Stelle ein neues Zitat. Da ich sowieso total auf Futurama stehe, dachte ich mir ich baue die Zitate als Welcome-Message in meine Rechner ein:

$ curl -Is slashdot.org | sed -n '5p' | sed 's/^X-//'
Bender: OK, but I don't want anyone thinking we're robosexuals.
$ curl -Is slashdot.org | sed -n '5p' | sed 's/^X-//'
Fry: I can burp the alphabet. A, B, D ... no, wait ...

Wenn ich aber bei allen meinen Rechnern die Zeile einbinde, hat das irgendwie ein bisschen was von DOS-Attacke. Muss ja nicht sein. Mit einem Einzeiler hab ich mir die Quotes erstmal alle besorgt:

target="/path/to/file/018" ; while true ; do quote="$(curl -Is slashdot.org |sed -n '5p' |sed 's/^X-//')" ; if [ $(grep "$quote" $target |wc -l) -lt 1 ]; then echo $quote >> $target ; echo $quote ; sleep 1 ; fi ; done

Hier gibt’s alle Quotes die der Einzeiler bis jetzt gesammelt hat: http://zwetschge.org/paste/018

Futurama Quotes beim Login unter Ubuntu:

$ wget http://zwetschge.org/paste/018 -O ~/.futurama
$ vi ~/.bashrc
quotes="$HOME/.futurama"
if [[ $- == *i* ]]; then
echo " "
rnd=$((RANDOM % $(cat $quotes | wc -l)+3)) ; sed -n "${rnd}p" $quotes
fi

Einloggen oder Shell starten sieht dann wie folgt aus:

$ ssh user@host
user@host password:
Linux host 2.6.32-22-generic #33-Ubuntu SMP Wed Apr 28 13:27:30 UTC 2010 i686 GNU/Linux
Ubuntu 10.04 LTS
[...]
You have new mail.
Bender: You can't count on God for jack! He pretty much told me so himself.
user@host:~$

August 29 2010

20:31

Explain | Shell-Kommandos visualisiert erklären

Neulich bin ich über das github Profil von Peter Hofmann gestolpert. Darin befand sich ein Projekt, welches ich sehr interessant fand.

Explain versucht Shell Kommandos zu erklären und zu visualisieren. Gerade für Blogs oder andere Dokumentationen finde ich das mehr als sinnvoll. Es erstellt aus einem simpel gestricktem Markdown File eine ASCII-Art ähnliche Erläuterung des Kommandos. Beispielsweise:

$ ./explain.py command.markdown
find . -iname '*.png' -exec echo '<br><img src="{}">' \; > gallery.html
\__/ | \___________/  \________/ \___________________/ |  \___________/
  |  |       |             |               |           |        |
  |  |       |             |               |           |        \- Ausgeben nach
  |  |       |             |               |           |           gallery.html
  |  |       |             |               |           |
  |  |       |             |               |           \- find Syntax Ende.
  |  |       |             |               |
  |  |       |             |               \- mit folgendem Inhalt aus.
  |  |       |             |
  |  |       |             \- und führe echo
  |  |       |
  |  |       \- alle Dateien die mit .png enden
  |  |
  |  \- im aktuellen Verzeichnis
  |
  \- Finde (via find)

(PlainText: http://zwetschge.org/paste/015)

Die Syntax des Files das zur Deklaration der Ausgabe dient:

find . -iname '*.png' -exec echo '<br><img src="{}">' \; > gallery.html
---- ! -------------  ---------- --------------------- ! -------------

Finde (via find)

im aktuellen Verzeichnis

alle Dateien die mit .png enden

und führe echo

mit folgendem Inhalt aus.

find Syntax Ende.

Ausgeben nach gallery.html

Die Trennzeichen  sind via Parameter austauschbar und auch ansonsten tut das kleine Python Script seinen Job hervorragend. Sollte demnächst mal wieder ein Kommando erläutert werden müssen, werde ich definitiv darauf zurückgreifen. Weitere Beispiele auch unter:

[1] http://www.uninformativ.de/?section=news&ndo=single&newsid=118
[2] http://github.com/vain/explain

August 16 2010

17:42

Git | Dotfiles des Home-Dirs verwalten

Permanent an verschiedenen Workstations zu sitzen hat Nachteile. Heimrechner(Xubuntu), Arbeits-PC(Xubuntu), Macbook und im blödsten Fall noch (private) Server. An all diesen Maschinen entwickelt man Vorlieben, bestimmte Software zu bedienen, entsprechend anzupassen oder zu konfigurieren. Es müssen nicht mal elementare Sachen sein. Selbst nicht vorhandene triviale Kleinigkeiten wie zum Beispiel Anpassungen der .dircolors oder .bashrc bzw. .bash_aliases sind manchmal extrem nervig.

“Warum funktioniert mein Alias hier eigent…..ah. Falscher Host :/ “

Das brauche ich hier warscheinlich niemandem weiter erläutern ;)

Grundsätzlich bemühte ich mich einen kleinen Satz ausgewählter .dotfiles meiner Home-Verzeichnisse auf neue Systeme zu kopieren bzw zu aktualiseren. Aber bei einer Änderung >4 Hosts neu umkopieren? Oder Änderungen sogar per Hand separat ausführen? Jedenfalls entwickelt mit der Zeit jeder, der auf diese Problemstellung trifft, seinen eigenen Weg alle Dotfiles synchron zu halten. Hier ist nun der (seit neuestem) Meinige.

Ich benutze ein Git-Repository. In diesem Repo befinden sich alle Dotfiles die ich im alltäglichen Gebrauch benötige. Das sieht ungefähr so aus:

dotfiles/
|-- .bashrc
|-- coming-home.bash
|-- .csshrc
|-- .dircolors
|-- .dmrc
|-- .git/
|-- .gitconfig
`-- .vimrc

(Aus Gründen der Lesbarkeit gekürzt)

Alle Änderungen, die für die Configs anstehen, kann ich nun hier tätigen. Füge neue Aliase hinzu, ändere meine Editor einstellungen für Vim oder ähnliches. Für die automatische Einrichtung habe ich “coming-home.bash” geschrieben. Das Script filtert automatisch alle Verzeichnisse(., .., .git) und Files (z.B. das Script selbst) die nicht ins $HOME-Verzeichnis gehören und kopiert alles was übrig bleibt in das Home-Dir des aktuellen Benutzers.

#!/bin/bash
# get dotfiles
dotfiles=$(ls -la | grep -v ^d | awk '{print $8}'| grep -v ^coming-home.bash$ )
mode=${1:-normal}

for x in $dotfiles; do
    # fishing errors
    if [ ! -e $x ] ; then echo "error reading files" ; exit 1 ; fi
    # keep old .bashrc
    if [ $x = ".bashrc" ]; then
        if [ ! -e $HOME/.bashrc_old ]; then
            cp $HOME/.bashrc $HOME/.bashrc_old
        fi
    fi
    # forced hook
    if [ $mode = "--hook" ]; then echo "hook: copying $x" ; /bin/cp -r $x $HOME/ ; fi
    # standard run
    if [ $mode != "--hook" ]; then /bin/cp -i $x $HOME/ ; fi
done

Git bietet weiterhin noch schöne Möglichkeiten, Operationen bei Änderungen automatisch ausführen zu lassen. Hooks. Ein post-commit-Hook führt das Skript jetzt nach jeder eingespeicherten Änderung automatisch aus.

.git/hooks/post-commit:

#!/bin/bash
$GIT_DIR/../coming-home.bash --hook

Anwendungsbeispiel:

$ git commit -a -m "added aliases and changed colors in vimrc"
hook: copying .bashrc
hook: copying .csshrc
hook: copying .dircolors
hook: copying .dmrc
hook: copying .gitconfig
hook: copying .vimrc

So kann ich jetzt Änderungen der Dotfiles im Git-Repo durchführen und habe diese gleich darauf im Home-Verzeichnis. Dieses Repo existiert (über einen Git-Server verwaltet) auf jedem meiner Hosts. Um im Fallbeispiel zu bleiben: Gehe ich morgen in die Arbeit, aktualisiere ich das (auch dort vorhandene) Repo und führe coming-home.bash aus.

By the Way: An dieser Stelle habe ich auch über Automatisierung nachgedacht. Git-Hooks gibt es für die verschiedensten Situationen:

Pre-Commit (vor speichern einer Änderung)
Post-Update (Nach dem pushen auf den Server)
usw.

Für eine Situation darf es diese Automatisierung aber nicht geben. Nämlich nach dem post-clone (unmittelbar nach dem Herunterladen eines Repos). Automatische Skripte die nach dem Herunterladen ausgeführt werden könnten große Schäden anrichten, wenn man so drüber nachdenkt.

July 16 2010

15:39

Thunar | Netzwerk-Ressourcen einbinden mit Gigolo

Xubuntu hat ein schönes Tool von Haus aus dabei, welches sich Gigolo nennt. Gigolo soll dazu dienen Netzwerk-Ressourcen zu verwalten und integrieren. Nun, Ressourcen einbinden funktioniert wunderbar. Nur sollten sich Diese auch öffnen lassen. Irgendwie. Oder auch nicht.

Gigolo möchte also Thunar zum Öffnen dieser Orte benutzen (voreingestellt). Allerdings unterstützt Thunar in der in Xubuntu vorliegenden Version noch keine Netzwerk-Ressourcen. In diversen Threads bei UbuntuUsers fand ich auch Lösungsansätze die empfahlen Nautilus zu installieren. Aber ich finde Thunar schön, weshalb ich mich gegen diesen Ansatz entschied. Nachdem ich mich dann (erneut) 20 min durchs Netz gegreppt habe, fand ich eine Alternative.

Die aktuelle Entwicklerversion von Thunar setzt auf Gio auf. Dem selben Manager den auch Nautilus für Netzwerksachen nutzt.

Zu finden ist diese unter: https://launchpad.net/~xubuntu-dev/+archive/ppa

Neue Sources in /etc/apt/sources.list hinzugefügt

deb http://ppa.launchpad.net/xubuntu-dev/ppa/ubuntu lucid main
deb-src http://ppa.launchpad.net/xubuntu-dev/ppa/ubuntu lucid main

und Thunar updaten. Gigolo kann mittels Thunar die eingebundenen Ressourcen öffnen. Gigolo funktioniert. Tada.

Allerdings interessiert es mich trotzdem, ob ich einfach nur Fehler im Handling mache oder da seitens Xubuntu etwas Abstimmungstechnisches schief lief. Immerhin ist es schon die zweite Xubuntu Installtion bei der dieser Umstand eintritt.

June 06 2010

09:32

Snapfish | Fotobücher erstellen mit Ubuntu

Vor kurzem war ich mit meiner besseren Hälfte für ca. 10 Tage in New York. Zu ihrem (gleich darauf folgenden) Geburtstag, hätte Sie sich gerne so ein “Fotobuch, was auch manchmal in der Werbung kommt” gewünscht :)   Stellte sich für mich (nach dem das Jetlag überwunden war :P ) die Frage wie ich sowas mit meinem aktuell laufenden Xubuntu hinbekomme. Löst man soetwas über Webinterface des Anbieters? Ist es notwendig zwielichtige Software zu installieren, mit der man sowas basteln kann? Warscheinlich müsste ich mir dann Windows wieder installieren? Ich muss ehrlich gestehen, ich hatte keine Ahnung.

Aufgrund einer bereits getätigten Bestellung von Fotos bei www.pixaco.de, beschloss ich also mein Glück dort zu versuchen. Musste aber feststellen, dass pixaco.de von HP aufgekauft wurde und jetzt Snapfish (www.snapfish.de) heisst. Qualitäts-, Service-, Lieferdauer-mäßig war alles gut gewesen und mein Account bestand noch, warum also nicht.

Ich muss sagen, dass ich im Allgemeinen sehr sehr postiv von dem ganzen Vorgang überrascht war. Einloggen, auf Fotobuch drücken und OS auswählen:
(Bilder verkleinert angehängt, mit Orginalgröße verlinkt)

snapfish-fotobuch-os

Linux Kernel 2.6, glibc 2.6. Muss ich zugeben, hört sich etwas abschreckend an. Ganz im Gegenteil verlief die Installation allerdings. Bei Auswahl des Radio-Buttons “Linux” , bekommt man vom Webserver seitens Snapfishs ein gut geschriebenes (soweit ich das mit meinem unterentwickelten Kenntnissen beurteilen kann) Perl-Skript zugeschoben, welches man einfach auszuführen hat.

snapfish-fotobuch-install

Sehr einfach, sehr schön, wenn ich mir überlege, dass das Software eines Drittanbieters ist, die nicht aus den Repos kommt. Und (warscheinlich) noch dazu “unfrei” ist. Jedenfalls, der Installtionsprozess ist nicht das einzige schöne daran. Auch die Software an sich läuft stabil, sieht gut aus und ist einfach zu benutzen.

snapfish-fotobuch-app
snapfish-fotobuch-addon

Auch Installation zusätzlicher Verzierungen oder sonstigem innerhalb der Software funktioniert wunderbar. Nach ca 4-5 Werktagen (von denen ich den Großteil damit verbracht habe das Buch überhaupt zu erstellen :D )  kam dann die Lieferung von Snapfish. Wie bereits erwähnt, wunderbare Qualität, schnell, schön. Finde es dabei auch awesome, dass alternative OS bei Entwicklung solcher, ich sag mal, kommerziellen Programme nicht zu kurz kommen. Danke pixaco, Snapfish oder HP. Wie auch immer du dich jetzt nennen magst. Ich muss allerdings dazusagen, dass ich nicht weiss, was andere Anbieter in dem Bereich parat haben. Snapfish war jetzt sozusagen mein Glückstreffer und ich musste mich gar nicht wirklich gross erkundigen wo man mit Linux soetwas machen lässt/erstellen kann. Jedenfalls, meine dickste Empfehlung an Snapfish.


DSC01221

May 31 2010

19:50

Mail | Evolution und sein K.O.-Kriterium

Vor längerer Zeit suchte ich mir einen neuen Mail-Client. Mein Thunderbird 2.XY (ich kann mich wirklich nicht mehr an den genauen Release in Xubuntu 9.10 erinnern) hat desöfteren zicken gemacht. Meine drei E-Mail-Konten werden allesamt von Thunderbird sortiert. Da dies IMAP-Postfächer sind, überträgt sich die Verschiebung von Mails auch auf meine anderen 3 Mail-Clients. Unter anderem Mail von Apple am Macbook, iPhone Mail und Xubuntu Thunderbird zuhause. So muss ich nur einen Regelsatz pflegen und hab trotzdem überall geordnete Mails.


evo-logo3

Nun der Single-Point-of-Failure (oder auch Arbeits-PC) der 24 Std in Betrieb ist und Mails sortiert, hängt sich ständig auf, stürzt ab oder ignoriert willkürlich Filter. Gerade als ich 4 Wochen nicht in der Arbeit und teils auch in den USA war, war es sehr ungünstig nach 3 Tagen festzustellen das im Posteingang 600 unsortierte Mails liegen. Ein Umstieg stand an. Habe mich für Evolution entschieden und fand das auch im ersten Moment sehr sehr schön gemacht. Es gibt nur einen riesen Nachteil. Es ist nicht möglich, dass eintreffende Mails automatisch sortiert werden.

Auch der Lösungsansatz von http://ubuntuforums.org/showthread.php?t=99930 konnte mir nicht helfen.

Jedesmal STRG + Y zu drücken kommt absolut nicht in Frage. Das funktioniert auch nicht, da ich nicht rund um die Uhr in der Arbeit bin. Später habe ich versucht dieses Event irgendwie über CronJob aus dem Source-Code starten zu lassen. Ohne Erfolg.

Ich muss wirklich sagen, schöne Arbeit Evolution. Würde dieses tolle Mailprogramm auch sehr gerne weiterhin benutzen. Aber unter diesen Umständen auf keinen Fall. Schade, dass wirklich schöne Software immer an irgendwelchen Kleinigkeiten scheitern. Was keinen Vorwurf gegenüber der Software selbst darstellt. Eher ein kleines Makel was für einzelne User wichtig wäre. So bin ich nun zu Thunderbird 3.0 migriert und liege Nachts wach, aus Angst morgens von Mails überrollt zu werden ;)

May 26 2010

19:22

Bash | Inkrement-Methoden und Effizienz

Desöfteren schlage ich mich in Bash-Scripting mit den Meldungen “unärer Operator” und ähnlichen Fehlern herum. Inkrementierungen über i=$[$i+1] funktionieren unter entsprechenden Umständen nicht. In Bash mit Zahlen umzugehen ist garnicht so leicht, finde ich. Manchmal werden die Zahlen als Char statt Int interpretiert und manchmal darf man zu einer Variable mit Wert 0 keine Addition durchführen. Das kann natürlich an meinen mangelnden Fähigkeiten liegen, aber heute habe ich mich auf die Suche nach Lösungen zu diesem Thema gemacht.

# 1
let i+=1 # increment
let i-=1 # decrement

# 2
let i++ # increment
let i-- # decrement

# 3
i=$[$i+1] # increment
i=$[$i-1] # decrement

# 4
i=$((i+1)) # increment
i=$((i-1)) # decrement

# 5
((i++)) # increment
((i--)) # decrement

# 6
i=$(expr $i + 1) # increment
i=$(expr $i - 1) # decrement

# 7
: $[ n = $n + 1 ] # increment
: $[ n = $n - 1 ] # decrement

Das waren so die üblichen Varianten mit denen ich mir die letzten Monate geholfen habe. Mitunter wirklich unschöne Sachen. Auf http://tldp.org/LDP/abs/html/declareref.html bin ich dann allerdings auf eine sehr elegante Lösung gestossen. Via “declare” lässt sich eine Variable auf einem bestimmten Typ festnageln. “declare -i VAR” deklariert (haha) die Variable “VAR” nach Integer. So lässt sich quasi direkt damit rechnen. Anschliessend das Beispiel um im Bild zu bleiben:

# Declare Variante
declare -i i # -i = integer
i=$i+1 # increment
i=$i-1 # decrement

Das geht wiederrum auch mit mehreren Variablen, Zahlen und Rechenoperationen. Ein kleines einzeiliges Beispiel:

j=5 ; k=12 ; declare -i i ; i=$j*10+$k/2 ; echo $i

Natürlich gibt es auch noch andere lustige Modi die man seiner Variable aufs Auge drücken kann:

declare -r # readonly
declare -a # array
declare -x # export variable
declare -f # function

Alles in Allem sehr nett. Werde jetzt erstmal ein paar Skripte umbauen. Denke ich.

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.