Ich wollte nur [...] und dann ist das Universum explodiert.

Projects
Books
Archive
About









    Permalink
  1. 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!


  2. Permalink
  3. Taskwarrior | The better-task-shell

    Eigentlich wollte ich das Projekt task-shell-ng nennen. Aber so gut ist es dann doch nicht geworden. Stattdessen hat es sich aber den Prefix better verdient ;)

    Als ich vor ca. einem Monat Taskwarrior für mich entdeckt habe, war eigentlich alles gut. Ich hab mich über den integrierten interactive Mode wirklich gefreut. Anfangs. Mit der Zeit habe ich aber festgestellt, dass mich dieses “Ding” fast in den Wahnsinn treibt. Mir persönlich fehlen einfach elementare Features wie einfaches Cursor bewegen nach vorne und zurück. Überhaupt eine History zu haben wäre schon ein enormer Vorteil.

    Ich hab mir dann kurzer Hand selber eine Taskwarrior Shell Variante gebaut, die im großen und ganzen auf einer Bash basiert.

    Features:

    • History vorwärts und rückwärts via Pfeiltasten
    • Cursorbewegung vorwärts und rückwerts in der aktuellen Zeile
    • Alle Kommandos nativ benutzbar ( $ add pri:H pro:Living Miete zahlen )
    • ID’s direkt nutzbar ( $ 34 edit oder $ 12 pri:H )
    • separate Logging Funktion in $HOME/.better-task-shell_history
    • OS Befehle weiterhin nutzbar! ( $ vim /home/user/foobar.txt )
    • Automatische Erkennung von doppelten Aliases
    • Automatische Alias Generierung fuer os-binaries ( $ ls  = task ls  ; os-ls = /bin/ls )
    • Auto-Komplettierung aller Taskwarrior Befehle und definierte Aliase

    Known Bugs:

    • Neu angelegt tasks  können derzeit noch nicht via ID aufgerufen werden.
      $ add Uberweisung einwerfen
      Created Task 45
      $ 45 pri:H
      bash: 45: Kommando nicht gefunden
      Für beim Start bestehende Einträge funktioniert dies allerdings problemlos.
    • Mode -v ist bis jetzt noch nicht benutzbar aber bereits implementiert.

    Das ganze gibts jetzt unter http://github.com/noqqe/better-task-shell

    Usage:

    git clone git@github.com:noqqe/better-task-shell.git
    $ cd better-task-shell
    $ ./better-task-shell


  4. Permalink
  5. PostgreSQL | 1000 und 1 Query

    Zur Zeit spiele und bastle ich nebenher mit PostgreSQL rum. Überlege ob ich mal eine alternative DB für das Zombie-Revolution-Environment an den Start bringe…

    Für meinen Use-Case scheint das allerdings nur begrenzt von Nutzen zu sein. Ich mache vielleicht etwas falsch, aber wenn ich 1000 Queries in MySQL kippe, dauert nur einen Bruchteil so lange wie in postgreSQL. Um das zu veranschaulichen:

    $ time for x in $(seq 1 1000) ; do mysql -u root -ppw -e "insert into foobar.foo values ($x, now());" ; done
    real 0m7.349s
    user 0m0.060s
    sys 0m0.380s

    $ time for x in $(seq 1 1000) ; do psql --quiet -d foobar -c "insert into foobar values ($x, now());" ; done
    real 1m28.363s
    user 0m37.450s
    sys 0m13.020s

    Kann mir jemand sagen woran das liegt? Ich kann mir nur schwer vorstellen das PostgreSQL so hinterher hinkt.


  6. Permalink
  7. 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 :)


  8. Permalink
  9. Minecraft + Git + Bash = <3

    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
    # Update
    # oder alternativ:
    $ git checkout -f

    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 Sodom und Gomorra 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 :)


  10. Permalink
  11. Beats | Eine in Ruby geschriebene Drummachine

    Neulich habe ich voller Begeisterung das Drummachine Projekt Beats entdeckt. Beats stellt so in etwa die Musicbox für Nerds dar. In einem Verzeichnis mit einem Set an *.wav Dateien (wohl der Standard) legt man eine Art Konfigurationsdatei, welche durch Beats interpretiert wird. In einer gewissen Syntax beschreibt man dieses Lied und dessen Abfolge.

    Das Traurige an der Sache ist eigentlich lediglich, dass ich mir bewusst geworden bin, wie wenig Kreativität/Können ich im musikalischen Bereich vorzuweisen habe. Teilweise sind beim Herumexperimentieren zwar Interessante Ergebnisse entstanden, aber nichts wofür ich mich nicht schämen müsste ;)

    $ beats song1.txt song.wav
    $ open song.wav

    Ich hab dann allerdings kurzer Hand begonnen, den Vorgang zu automatisieren. Erst wollte ich es outsourcen, aber dann habe ich es doch automatisiert. Da die ganze “Ich baue mir ein neues Lied”-Sache nur auf einem einzigen File beruht, dachte ich mir dass sich das mit Sicherheit auch automatisch generieren lässt.

    Das Skript das dabei herauskam, taufte ich randombeats. Wie alles was ich in letzter Zeit tue habe ich es natürlich auf github veröffentlicht.

    https://github.com/noqqe/randombeats

    Benutzung:

    Ins jeweilige Verzeichnis mit den Roh-Daten kopieren/wechseln und Skript ausführen.

    $ git clone http://github.com/noqqe/randombeats
    $ cp randombeats/randombeats.bash /path/to/music
    $ cd /path/to/music
    $ ./randombeats.bash > randomsong.txt
    $ beats randomsong.txt
    $ open randomsong.wav

    Raus kommen allerlei sehr Interessante und manchmal auch schöne Rhythmen. Aber manchmal auch akkute Ohrenschmerzen verursachen. Ein paar davon sammle ich mittlerweile in einem separaten Branch im Git-Repo. Diesen kann ich aber nicht uploaden, weil die größe meines Github Accounts auf 300MB beschränkt ist. Aber vielleicht finde ich anderweitig Möglichkeiten die Ergebnisse zu publizieren.

    Mittlerweile habe ich folgenden Befehl in einer Schleife laufen.

    ./randombeats.bash > rnd.txt && beats rnd.txt && open rnd.wav

    An Feedback, Kritik oder Anmerkungen zu Verbesserungen an den Eckdaten des Skripts bin ich wie immer sehr interessiert :)

    Update: Kurze WAV-Files generiert und als Beispiel hochgeladen.

    randombeats example 1
    randombeats example 2


  12. Permalink
  13. Shell-Zauberei | Namensliste in MySQL Datenbank einspeisen

    Code
    for x in $(mysql --batch -u root --password=passw0rd -e "USE rtdb; SELECT DISTINCT id FROM Users;" | grep -v ^id); do mysql -u root --password=passw0rd -e "USE rtdb; UPDATE Users SET Name=\"$(sed -n $(($RANDOM % $(cat Names | wc -l) +1 ))p Names)\" WHERE id=\"$x\" ;" ; done

    Hintergrund
    Wie auch schon beim letzten mal dreht es sich wieder um die Anonymisierung der RequestTracker Datenbank für die ich zur Zeit an einem Statistik Tool arbeite. Diesmal will ich aber nicht die EmailAdressen ändern, sondern die Namen der Benutzer. Da ich diese nicht so einfach generieren lassen kann, habe ich mir aus dem Interweb eine Liste mit Namen besorgt und mit diesen Namen die eingetragenen überschrieben. Jetzt kann ich endlich den Post über das Statistik Tool schreiben und mit Beispielen versehen :)

    Funktion
    Das Ganze läuft wie folgt ab: Für jede ID die ich mittels Datenbank-Verbindung in die For-Schleife einbette, setze ich einen UPDATE Befehl ab, der die Tabelle “Users” und das Feld “Name” aktualisiert. Der Aktualisierungsvorgang passiert aber generisch. Das heisst ich setze den Namen des Users auf einen zufällig ausgewählten neuen Namen aus der Datei “Names”. Das habe ich mit sed -n p FILE gelöst, was sicher auch schöner geht, aber für meine Zwecke hat es ausgereicht.

    About: “Ein Byte der Shellzauberei” – Kategorie: http://noqqe.de/archives/category/shell-zauberei


  14. Permalink
  15. Shell-Zauberei | Emailadressen in MySQL Datenbank anonymisieren

    Code
    for x in $(mysql -u root --password=passw0rd --batch -e "use rtdb; select id from Users" | grep -v ^id); do mysql -u root --password=passw0rd -e "use rtdb; UPDATE Users SET EmailAddress=\"$x@mail.com\" WHERE id=\"$x\"; "; done
    Hintergrund
    Ich arbeite seit kurzem an einem kleinen Statistik Tool für den RequestTracker von Bestpractical. Einem Ticket-System. Um Beispiele für dieses Tool generieren zu können, brauchte ich eine manipulierte Datenbank. Datenschutz. EmailAdressen mit anderem Inhalt überschreiben.

    Funktion
    Im Endeffekt ist es nur eine For-Schleife, die alle User ID’s aus der RequestTracker Datenbank (Table: Users) ausliesst und für jeden gefundenen Eintrag die EmailAdresse auf “ID@mail.com” setzt. So bleiben die Daten auswertbar, sind aber “anonym”.

    About: “Ein Byte der Shellzauberei” – Kategorie: http://noqqe.de/archives/category/shell-zauberei


  16. Permalink
  17. Shell-Zauberei | Eine Einleitung

    Ich möchte mit diesem Post eine kleine Reihe von Blogposts beginnen. Diese Eintragsreihe möchte ich in unbestimmter Länge und Frequenz in meinen Blog etablieren. Der Gedanke zu dieser Aktion, die ich “Ein Byte der Shell-Zauberei” nennen werde, geistert mir schon seit ca. zwei Monaten im Kopf herum.

    Mein Job als Administrator von Debian/Linux Systemen verlangt von mir oftmals Automatisierung und Shell-Scripting in mal größerem und auch kleinerem Umfang. Oft lassen sich derartige Aufgaben sehr leicht in einem Einzeiler/Oneliner auf dem Terminal lösen. Ich mag es, wenn Lösungen schnell und einfach durchzuführen sind, besonders mit Bash. Der Anspruch dieser Aufgaben variiert genauso wie deren Umfang. Die “Zauberei” im Titel der Aktion darf also wahlweise auch etwas ironisch verstanden werden.

    Als mir die Idee kam, dachte ich mir ehrlich gesagt, dass ich für eine solche Reihe wahrscheinlich nicht genügend Kanonenfutter hätte. Sprich, genügend einzeilige Bash Zauberei, die ich im Kontext dieser Reihe posten könnte. Ich beschloss den Gedanken noch nicht sofort zu verwerfen und stattdessen ein paar dieser Einzeiler zu speichern und zu sehen wie viele es werden.

    In den letzten Zwei Monaten waren das jetzt ca. 12 Stück die ich als “Blogwürdig” empfand. Ich denke, das reicht mir für die Kategorie.

    Aufbau

    Die Posts werden immer gleich aussehen und folgende Punkte enthalten:

    • Code
    • Hintergrund
    • Funktion
    • About “Shell-Zauberei”

    Informationen

    Kategorie URL: http://noqqe.de/archives/category/shell-zauberei


  18. Permalink
  19. statistical | It’s about internal functions.

    Als ich statistical auf GitHub hochgepushed habe, fing ich an mir Gedanken über die Leistungsfähigkeit des Scripts zu machen. Ich meine es verhielt sich in Anbetracht der Daten (in meinen Augen) wunderbar. Die Key Länge wird bis zu 4 Tab-Längen mit skaliert, genauso wie die Values, in Form der Bars. Aber wie verhält sich es mit größeren Datenmengen?

    Diesbezüglich wollte ich eine kleine For-Schleife benutzen um mehrere zufällige Werte zu generieren und in statistical zu pipen.

    time for x in $(seq 1 6000); do echo "$x:$RANDOM" ; done | statistical > /dev/null

    Das Ergebnis war mit 6000 Datensätzen und guten 7 Minuten relativ ernüchternd. Vor kurzem hat mich dann auch noch Vain via GitHub auf die Geschwindigkeit von statistical hingewiesen. In seinem Fork, hat er alle extern spawnenden Befehle gegen Bash interne Funktionen ausgetauscht. Siehe da:

    real 0m7.788s
    user 0m7.610s
    sys 0m0.250s

    Wahnsinn oder? Durch den Austausch von awk und grep durch interne Bash Funktionen wird das ganze ernsthaft 23x mal schneller. Vielen Dank an Vain an dieser Stelle!


Older »