<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
  <channel>
    <title>Memento Cache</title>
    <link>https://tromm.net/blog/</link>
    <description>Recent content in Blogs on Memento Cache</description>
    
    
    <language>de-de</language>
    
    
    
    
    
    <lastBuildDate>Fri, 26 Oct 2018 18:55:02 +0100</lastBuildDate>
    
    <atom:link href="https://tromm.net/blog/" rel="self" type="application/rss+xml" />
    
    <item>
      <title>Org-Mode für unterwegs mit Orgzly &amp; Syncthing</title>
      <link>https://tromm.net/blog/orgzly_und_syncthing/</link>
      <pubDate>Fri, 26 Oct 2018 18:55:02 +0100</pubDate>
      
      <guid>https://tromm.net/blog/orgzly_und_syncthing/</guid>
      <description>

&lt;p&gt;Ich suchte schon länger nach einer geeigneten Lösung, wie ich Notizen, erstellt mit Emacs unter dem &lt;a href=&#34;https://orgmode.org/&#34;&gt;Org Mode&lt;/a&gt;, auch mobil lesen und pflegen kann. Bisher probierte ich z.B. &lt;em&gt;MobileOrg&lt;/em&gt; mit der entsprechenden Android-App oder aber die App &lt;em&gt;Orgzly&lt;/em&gt; in Kombination mit Nextcloud aus.&lt;/p&gt;

&lt;p&gt;Doch erst das Zusammenspiel von &lt;a href=&#34;http://www.orgzly.com/&#34;&gt;Orgzly&lt;/a&gt; und &lt;a href=&#34;https://syncthing.net/&#34;&gt;syncthing&lt;/a&gt; hat mich als mobile Alternative überzeugt, insbesondere was eine flüssige und nahtlose Synchronisation angeht.&lt;/p&gt;

&lt;h2 id=&#34;syncthing-für-den-desktop&#34;&gt;Syncthing für den Desktop&lt;/h2&gt;

&lt;p&gt;&lt;em&gt;Syncthing&lt;/em&gt; ist offen, dezentral und kommuniziert verschlüsselt von Ende zu Ende. Es ist für die gängigen Betriebssysteme frei verfügbar. Unter einem aktuellen Debian/Ubuntu kann es direkt über den Package-Manager installiert werden:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;apt install syncthing
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Nach dem Aufruf &lt;code&gt;syncthing&lt;/code&gt; kann die Einrichtung anhand einer Web-Oberfläche im Browser unter &lt;code&gt;localhost:8384&lt;/code&gt; vorgenommen werden. Hier können Verzeichnisse und Geräte für andere &lt;em&gt;syncthing&lt;/em&gt;-Instanzen einfach angemeldet werden, was die &lt;a href=&#34;https://docs.syncthing.net/intro/getting-started.html&#34;&gt;Dokumentation&lt;/a&gt; bereits gut beschreibt. Unter dieser Web-Oberfläche kann somit das zu synchronisierende Org-Verzeichnis berücksichtigt werden, z.B. &lt;code&gt;~/Documents/org&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Es können dabei auch Dateien von der Synchronisation ausgeschlossen werden. Dies macht Sinn für die Archiv-Dateien des Org-Modes. Diese Dateien werden ausgenommen, wenn z.B. unter &lt;code&gt;~/Documents/org&lt;/code&gt; die Datei &lt;code&gt;.stignore&lt;/code&gt; mit dem folgenden Inhalt angelegt wird:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;*.org_archive
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Bei permanenter Nutzung lohnt sich natürlich die Einrichtung eines &lt;a href=&#34;https://docs.syncthing.net/users/autostart.html&#34;&gt;Autostarts&lt;/a&gt;. Bei einem Desktop vorzugsweise als Daemon über einen &lt;em&gt;Systemd User Service&lt;/em&gt;. Ist der Daemon eingerichtet, kann dieser beim Start der &lt;em&gt;GNOME Shell&lt;/em&gt; aktiviert werden, indem unter dem Verzeichnis &lt;code&gt;~/.config/autostart&lt;/code&gt; z.B. eine  Datei, wie  &lt;code&gt;synching-launcher.desktop&lt;/code&gt;, mit dem folgendem Inhalt hinterlegt wird:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;[Desktop Entry]
Version=1.0
Type=Application
Terminal=false
Icon[de_DE]=gnome-panel-launcher
Exec=systemctl --user start syncthing.service
Name[de_DE]=syncthing launcher
Name=syncthing launcher
Icon=gnome-panel-launcher
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Als zusätzliche Option gibt es noch eine schöne &lt;em&gt;GNOME Shell Extension&lt;/em&gt; namens &lt;a href=&#34;https://extensions.gnome.org/extension/989/syncthing-icon/&#34;&gt;Syncthing Icon&lt;/a&gt; (alternativ via Ubuntu SW-Center installierbar), mit welcher sich der aktive Status von &lt;em&gt;syncthing&lt;/em&gt; in der Statusleiste anzeigen und steuern lässt.&lt;/p&gt;

&lt;h2 id=&#34;syncthing-orgzly-für-das-smartphone&#34;&gt;Syncthing &amp;amp; Orgzly für das Smartphone&lt;/h2&gt;

&lt;p&gt;Auf dem Smartphone werden 2 Apps benötigt. &lt;em&gt;Syncthing&lt;/em&gt; für die Synchronisation und &lt;em&gt;Orgzly&lt;/em&gt; für die eigentliche Bearbeitung der eigenen Org-Notizen, also quasi als mobile und &lt;em&gt;abgespeckte&lt;/em&gt; Alternative gegenüber dem Org-Mode unter Emacs.&lt;/p&gt;

&lt;h3 id=&#34;syncthing-app&#34;&gt;Syncthing-App&lt;/h3&gt;

&lt;p&gt;&lt;em&gt;Syncthing&lt;/em&gt; ist als gleichnamige App für Android unter &lt;a href=&#34;https://f-droid.org/en/packages/com.nutomic.syncthingandroid/&#34;&gt;F-Droid&lt;/a&gt; oder unter &lt;a href=&#34;https://play.google.com/store/apps/details?id=com.nutomic.syncthingandroid&amp;amp;hl=de&#34;&gt;GooglePlay&lt;/a&gt; verfügbar. Die Einrichtung der zu synchronisierenden Geräte und Verzeichnisse erfolgt analog dem Desktop. Nachdem mit der App die jeweiligen Schlüssel bzw. IDs  von Desktop- und Smartphone-Instanzen gegenseitig bekannt gemacht und freigegeben wurden, kann man nun auf das vom Desktop freigegebene Org-Verzeichnis zugreifen.&lt;/p&gt;

&lt;h3 id=&#34;orgzly&#34;&gt;Orgzly&lt;/h3&gt;

&lt;p&gt;Orgzly ist ebenfalls unter &lt;a href=&#34;https://f-droid.org/en/packages/com.orgzly/&#34;&gt;F-Droid&lt;/a&gt; und &lt;a href=&#34;https://play.google.com/store/apps/details?id=com.orgzly&amp;amp;hl=de&#34;&gt;GooglePlay&lt;/a&gt; verfügbar.  Unter &lt;em&gt;Orgzly&lt;/em&gt; macht man nun das frisch synchronisierte Org-Verzeichnis bekannt mit: &lt;code&gt;Einstellung-&amp;gt;Synchronisieren-&amp;gt;Ablageorte-&amp;gt;Verzeichnis&lt;/code&gt; Das Verzeichnis findet man an einem Ort, welcher zum Beispiel, wie folgt, aussehen könnte: &lt;code&gt;/storage/.../Android/data.com.nutomic.syncthingandroid/files/org&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Tipp:&lt;/strong&gt; Um das konkrete Org-Verzeichnis auf dem Smartphone ausfindig zu machen, kann man sich in der &lt;em&gt;syncthing&lt;/em&gt;-App den physischen Ablageort des Verzeichnisses anzeigen lassen, indem man sich die Details des Verzeichnisses auflisten lässt.&lt;/p&gt;

&lt;p&gt;Zudem habe ich gute Sync-Erfahrungen mit den (noch experimentellen!) Funktionen unter &lt;code&gt;Einstellungen-&amp;gt;Synchronisieren-&amp;gt;Automatisch synchronisieren&lt;/code&gt; gemacht. Ich aktivierte hierzu die folgenden Funktionen:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Auto-Synchronisation&lt;/li&gt;
&lt;li&gt;Notiz erstellt&lt;/li&gt;
&lt;li&gt;Notiz aktualisiert oder gelöscht&lt;/li&gt;
&lt;li&gt;App gestartet oder fortgesetzt&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Wird nun zum Beispiel eine Org-Datei im o.g. Verzeichnis neu angelegt und synchronisiert, so wird diese von &lt;em&gt;Orgzly&lt;/em&gt; erkannt und berücksichtigt. D.h. neue Aufgaben und Notizen werden so unmittelbar automagisch mit eingebunden.&lt;/p&gt;

&lt;h2 id=&#34;alternative-syncthing-zwischenstelle&#34;&gt;Alternative Syncthing-Zwischenstelle&lt;/h2&gt;

&lt;p&gt;Die Synchronisation zwischen Smartphone und dem Desktop ist natürlich nur möglich, wenn beide Geräte gleichzeitig online sind. Wenn das selten der Fall sein sollte, dann macht es Sinn die Synchronisation über eine weitere, zwischengeschaltete Instanz laufen zu lassen, die permanent online ist. Hierzu ist z.B. ein stromsparender Raspberry Pi ausreichend, der als Zwischenstelle immer für einen Abgleich zur Verfügung stehen kann. Auf dem PI wäre dann in diesem Falle eine weitere Syncthing-Instanz installiert, welche zwischen Desktop und Smartphone vermittelt: &lt;code&gt;Desktop &amp;lt;-&amp;gt; PI &amp;lt;-&amp;gt; Smartphone&lt;/code&gt;&lt;/p&gt;

&lt;h2 id=&#34;emacs-etwas-reaktiver&#34;&gt;Emacs etwas reaktiver&lt;/h2&gt;

&lt;p&gt;Ist Emacs mit einer Org-Datei geöffnet, so ist es ärgerlich, wenn neue oder geänderte Notizen für diese Datei nicht direkt angezeigt werden, wenn diese z.B. von außen mit dem Smartphone erstellt oder geändert wurden. Ein manuelles, erneutes Laden wäre da eher nervig. Damit derartige Änderungen direkt automagisch angezeigt werden, aktiviert man den &lt;code&gt;auto-revert-mode&lt;/code&gt; beim Start von Emacs via folgender Ergänzung seitens &lt;code&gt;init.el&lt;/code&gt;:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;(global-auto-revert-mode t)
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Das automagische Anzeigen der synchronisierten Änderungen funktioniert tadellos, wenn die im Emacs geladene Datei keine ungespeicherten Änderungen enthält. Sollte dies mal nicht der Fall sein, so gibt Emacs (unabhängig vom &lt;code&gt;auto-revert-mode&lt;/code&gt;) beim darauf folgenden Speicherversuch einen Warn-Dialog aus:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;dateiname.org has changed since visited or saved.  Save anyway? (yes or no)&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Bei einem derartigen Fall ist es empfehlenswert, erst einmal die Änderungen unter einem anderen Dateinamen abzuspeichern und die beiden Dateien mit der Funktion &lt;code&gt;ediff-buffers&lt;/code&gt; abzugleichen.&lt;/p&gt;

&lt;p&gt;Wird allerdings eine Änderung gespeichert kurz bevor eine andere Änderung über die Synchronisation eingeht, so gibt es definitiv einen Konflikt, welcher nur von &lt;em&gt;syncthing&lt;/em&gt; selbst aufgezeigt werden kann. In diesem Falle wird die Datei mit der jüngsten Änderung von &lt;em&gt;syncthing&lt;/em&gt; übernommen und die andere Version wird als neue Datei mit dem Namen &lt;code&gt;&amp;lt;dateiname&amp;gt;.sync-conflict-&amp;lt;datum&amp;gt;-&amp;lt;zeit&amp;gt;.&amp;lt;org&amp;gt;&lt;/code&gt; im gleichen Verzeichnis abgelegt. Doch auch dann kann der User die Konflikte zwischen den beiden Dateien selbst auflösen, wofür sich ebenfalls wieder die Funktion &lt;code&gt;ediff-buffers&lt;/code&gt; anbietet.&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>Subshell Web Service</title>
      <link>https://tromm.net/blog/subshell-web-service/</link>
      <pubDate>Sat, 27 Dec 2014 12:18:12 +0100</pubDate>
      
      <guid>https://tromm.net/blog/subshell-web-service/</guid>
      <description>&lt;p&gt;Das folgende Bash-Skript antwortet auf einen &lt;em&gt;HTTP-Request&lt;/em&gt; mit der aktuellen Uhrzeit.&lt;/p&gt;

&lt;p&gt;Beim Start des Skripts werden 2 Prozesse gestartet:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;code&gt;nc&lt;/code&gt; horcht auf Port 8080 auf einen &lt;em&gt;HTTP-Request&lt;/em&gt; und leitet diesen an die &lt;em&gt;named Pipe&lt;/em&gt; weiter.&lt;/li&gt;
&lt;li&gt;Der zweite Prozess liest von der &lt;em&gt;named Pipe&lt;/em&gt; und leitet mitsamt &lt;em&gt;HTTP Return Code&lt;/em&gt; die aktuelle Zeit an &lt;code&gt;nc&lt;/code&gt; weiter.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Die &lt;em&gt;named Pipe&lt;/em&gt; in Kombination mit der &lt;em&gt;Subshell&lt;/em&gt; des 2. Prozesses ist der Kniff des Skripts damit auch die aktuelle Zeit über &lt;code&gt;nc&lt;/code&gt; als HTTP-Response zurück geliefert wird.&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;#!/bin/bash

if [ ! -p pipe ]; then
    mkfifo pipe
fi

while true; do 
    { 
       read line &amp;lt; pipe        
       echo -e &amp;quot;HTTP/1.1 200 OK\r\n&amp;quot;        
       echo $(date)     
     }  | nc -l 8080 &amp;gt; pipe
done
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Eine brauchbare Erklärung zur Subshell ist auf &lt;a href=&#34;https://unix.stackexchange.com/questions/127334/bash-subshell-creation-with-curly-braces&#34;&gt;Stackexchange&lt;/a&gt; zu finden.&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>Backup-Medium Erstellen und Booten</title>
      <link>https://tromm.net/blog/backup-medium-erstellen-und-booten/</link>
      <pubDate>Wed, 03 Dec 2014 00:55:12 +0100</pubDate>
      
      <guid>https://tromm.net/blog/backup-medium-erstellen-und-booten/</guid>
      <description>&lt;p&gt;Die folgenden Schritte beschreiben, wie der Inhalt von Gerät /dev/sdX nach /dev/sdY kopiert wird. Die entstandene Linux-Kopie (in diesem Fall Ubuntu) wird im Anschluss Boot-fähig gemacht.&lt;/p&gt;

&lt;p&gt;Wozu benötigt man dies? Ein Anwendungsfall ist z.B. ein Backup einer internen Festplatte auf ein externes Medium (z.B. USB-Festplatte). So kann beim Ausfall der internen Festplatte vom externen Medium gebootet werden.&lt;/p&gt;

&lt;p&gt;Als erstes ist von einem Live-Medium zu booten, wenn z.B. ein Backup des Betriebssystem erstellt werden soll. Die hier aufgezählten Schritte wurden mit Ubuntu 14.04 ausgeführt, sollten jedoch auch auf andere Linux-Distributionen übertragbar sein. Die oben aufgeführten Geräte /dev/sdX nach /dev/sdY werden hier lediglich als Beispiel verwendet und sind zu ersetzten durch die tatsächlich genutzten. Diese kann man z.B. durch das folgende Kommando ermitteln:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;sudo lshw -class disk
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Vorbereitung: Partitionen auflisten, um Typ und Größe zu prüfen; was ist die bootbare Systempartition?&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;sudo fdisk -l
&lt;/code&gt;&lt;/pre&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;Kopie von Gerät /dev/sdX auf Gerät /dev/sdY erstellen:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;sudo dd if=/dev/sdX of=/dev/sdY bs=1M conv=noerror
&lt;/code&gt;&lt;/pre&gt;&lt;/li&gt;

&lt;li&gt;&lt;p&gt;Mounten der kopierten Systempartition /dev/sdYn (n=Partitionsnummer):&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;sudo mount /dev/sdYn /mnt
&lt;/code&gt;&lt;/pre&gt;&lt;/li&gt;

&lt;li&gt;&lt;p&gt;Re-Mount der virtuellen Dateisysteme auf das kopierte System:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;sudo mount --bind /dev  /mnt/dev
sudo mount --bind /dev/pts  /mnt/dev/pts
sudo mount --bind /proc /mnt/proc
sudo mount --bind /sys  /mnt/sys 
&lt;/code&gt;&lt;/pre&gt;&lt;/li&gt;

&lt;li&gt;&lt;p&gt;Nun der Trick – Wechsel des Root-Verzeichnisses auf kopierte Systempartition (öffnet von nun an  root-Shell):&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;sudo chroot /mnt
&lt;/code&gt;&lt;/pre&gt;&lt;/li&gt;

&lt;li&gt;&lt;p&gt;Dies ermöglicht das erstellen der Grub2 Konfiguration /boot/grub/grub.cfg auf das kopierte System:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;update-grub
&lt;/code&gt;&lt;/pre&gt;&lt;/li&gt;

&lt;li&gt;&lt;p&gt;Grub2 auf dem kopierten Medium installieren:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;grub-install /dev/sdY
&lt;/code&gt;&lt;/pre&gt;&lt;/li&gt;

&lt;li&gt;&lt;p&gt;Grub2 Installation verifizieren:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;grub-install --recheck /dev/sdY
&lt;/code&gt;&lt;/pre&gt;&lt;/li&gt;

&lt;li&gt;&lt;p&gt;Im Anschluss sind noch die Mount-Einträge der Dateien /etc/fstab bzw /etc/mtab zu überprüfen. Es wird empfohlen die logischen Partitionsnamen, die dort eingetragen sind, z.B. /dev/sdYn, durch die entsprechende UUID zu ersetzten. Die UUIDs lassen sich, wie folgt, ermitteln:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;blkid
&lt;/code&gt;&lt;/pre&gt;&lt;/li&gt;

&lt;li&gt;&lt;p&gt;Rechner neu booten (und im Anschluss im Bios das entsprechende Laufwerk für /dev/sdY als Boot-Medium auswählen):&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;reboot
&lt;/code&gt;&lt;/pre&gt;&lt;/li&gt;
&lt;/ol&gt;
</description>
    </item>
    
    <item>
      <title>Subversion-Historie um Dateien bereinigen</title>
      <link>https://tromm.net/blog/subversion-historie-um-dateien-bereinigen/</link>
      <pubDate>Wed, 09 Nov 2011 00:28:12 +0100</pubDate>
      
      <guid>https://tromm.net/blog/subversion-historie-um-dateien-bereinigen/</guid>
      <description>&lt;p&gt;Es kann schon mal vorkommen, dass man versehentlich eine Datei in Subversion eincheckt, die dort einfach nichts verloren hat – zum Beispiel eine Konfigurationsdatei mit Zugangsdaten. Hier kommt man mit dem logischem Löschen anhand des Kommandos &lt;code&gt;svn rm file&lt;/code&gt; nicht wirklich weiter, da die Datei in der Historie verbleibt und so für andere weiterhin abrufbar ist. In diesem Fall hilft nur das Exportieren, Filtern und neue Aufsetzen des Subversion-Repositories, wie in den folgenden Schritten beschrieben wird.&lt;/p&gt;

&lt;p&gt;Im ersten Schritt wird ein Dump vom bestehenden Repository erstellt.&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;svnadmin dump /var/svn &amp;gt; svn-repo-dump
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Im Anschluss wird der Dump um die gegebenen Dateien, welche nicht mehr in der Historie geführt werden sollen, gefiltert.&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;svndumpfilter exclude path/to/pwd-file \
                      path/to-another/file \
                      &amp;lt; svn-repo-dump \
                      &amp;gt; svn-repo-dump-filtered
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Dann ist das bestehende Repository zu sichern und ein neues unter dem gleichen Pfad anzulegen.&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;mv /var/svn /var/svn.backup
svnadmin create /var/svn
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Zum Schluss wird dann noch der gefilterte Dump in das neu angelegte Repository eingespielt. Fertig.&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;svnadmin load --force-uuid /var/svn &amp;lt; svn-repo-dump-filtered 
&lt;/code&gt;&lt;/pre&gt;
</description>
    </item>
    
    <item>
      <title>Rekursive Suche nach Klassen in Java-Archiven</title>
      <link>https://tromm.net/blog/rekursive-suche-in-java-archiven/</link>
      <pubDate>Thu, 25 Aug 2011 23:58:12 +0100</pubDate>
      
      <guid>https://tromm.net/blog/rekursive-suche-in-java-archiven/</guid>
      <description>&lt;p&gt;In welchem Java-Archiv war noch einmal die Klasse X? Ist die Klasse Y vielleicht noch in einem anderen JAR vorhanden? Hier kann eine rekursive Suche im Dateisystem helfen indem als kleines Hilfswerkzeug die folgende Shell-Funktion in der Datei &lt;code&gt;~/.bashrc&lt;/code&gt; eingefügt wird.&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;search_jars() {
    search_dir=$1 
    search_term=$2 
    if [ -z &amp;quot;$search_term&amp;quot; -o -z &amp;quot;$search_dir&amp;quot; ]; 
    then
        echo &amp;quot;usage: search_jars [DIRECTORY] [SEARCH_TERM]&amp;quot;
        return 1
    fi
    echo &amp;quot;Searching JARs which contain classes matching \
        &#39;$search_term&#39; in &#39;$search_dir&#39;&amp;quot;
    find $search_dir -name &amp;quot;*.jar&amp;quot; -type f -exec \
         bash -c &#39;jar tvf &amp;quot;$1&amp;quot; | grep &amp;quot;$2&amp;quot;; \
             if [ $? == 0 ]; then \
                 echo &amp;quot;Found in JAR $1&amp;quot;; \
             fi&#39; {} {} $search_term \;
}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Das folgende Beispiel ruft search_jars auf der Konsole im aktuellen Verzeichnis auf und findet sämtliche Java Archive, die einen Klassennamen enthalten, welcher mit Locator.class endet.&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;&amp;gt;search_jars . Locator.class
Searching JARs which contain classes matching &#39;Locator.class&#39; in directory &#39;.&#39;
  com/sun/xml/bind/validator/DOMLocator.class
  com/sun/xml/bind/validator/Locator.class
  com/sun/xml/bind/validator/SAXLocator.class
Found in JAR ./jaxb1-impl.jar
  javax/xml/bind/ValidationEventLocator.class
Found in JAR ./jaxb-api.jar
  com/sun/tools/xjc/reader/dtd/bindinfo/DOM4JLocator.class
  com/sun/tools/xjc/reader/dtd/bindinfo/DOM4JLocator.class
Found in JAR ./jaxb-xjc.jar
&lt;/code&gt;&lt;/pre&gt;
</description>
    </item>
    
    <item>
      <title>SSH-Login ohne Kennwort in 3 Schritten</title>
      <link>https://tromm.net/blog/ssh-login-ohne-kennwort/</link>
      <pubDate>Sat, 27 Nov 2010 21:54:12 +0100</pubDate>
      
      <guid>https://tromm.net/blog/ssh-login-ohne-kennwort/</guid>
      <description>&lt;p&gt;&lt;em&gt;Schritt 1:&lt;/em&gt; Generierung des Schlüsselpaares&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;you@localhost:~$ ssh-keygen -t rsa

Generating public/private rsa key pair.
Enter file in which to save the key (/home/you/.ssh/id_rsa): 
Created directory &#39;/home/you/.ssh&#39;.
Enter passphrase (empty for no passphrase): 
Enter same passphrase again: 
Your identification has been saved in /home/you/.ssh/id_rsa.
Your public key has been saved in /home/you/.ssh/id_rsa.pub.
The key fingerprint is:
27:e7:1f:0c:99:7d:3b:86:cb:39:91:55:5b:0d:e5:20 you@localhost
The key&#39;s randomart image is:
+--[ RSA 2048]----+
|            E ooo|
|             . o+|
|               .+|
|           +  .. |
|        S * .o.  |
|         = ooo . |
|          . +.+  |
|           o.= . |
|            =.   |
+-----------------+
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;&lt;em&gt;Schritt 2:&lt;/em&gt; Erzeugung von ~/.ssh auf Remote Host (optional)&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;you@localhost:~$ ssh remote_user@remote.host &#39;mkdir -p .ssh&#39;
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;&lt;em&gt;Schritt 3:&lt;/em&gt; Öffentlichen Schlüssel publizieren&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;you@localhost:~$ cat ~/.ssh/id_rsa.pub | ssh remote_user@remote.host &#39;cat &amp;gt;&amp;gt; .ssh/authorized_keys&#39;
&lt;/code&gt;&lt;/pre&gt;
</description>
    </item>
    
    <item>
      <title>&lt;3 Relax NG</title>
      <link>https://tromm.net/blog/relax-ng/</link>
      <pubDate>Thu, 30 Sep 2010 00:04:12 +0100</pubDate>
      
      <guid>https://tromm.net/blog/relax-ng/</guid>
      <description>&lt;p&gt;Mir gefällt an Relax NG, dass es wesentlich lesbarer ist als das
schwergewichtigere W3C Schema XML – library.rnc:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;default namespace = &amp;quot;http://meingold.de/schema/any/library&amp;quot;

start = element library {
   element book {
      element title { xsd:string },
      element author { xsd:string },
      element isbn { xsd:string { pattern=&#39;[0-9]{3}-[0-9]{10}&#39; } },
      element quantity { xsd:positiveInteger  }
   }* 
}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Wenn man jedoch auf W3C Schema XML angewiesen ist, dann kann mit dem Kommandozeilen-Tool &lt;a href=&#34;http://www.thaiopensource.com/relaxng/trang.html&#34;&gt;Trang&lt;/a&gt; ein Relax NG Schema in ein W3C XML Schema umgewandelt werden.&lt;/p&gt;

&lt;p&gt;RNC -&amp;gt; XSD&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;trang library.rnc library.xsd
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Das generierte W3C Schema sieht dann, wie folgt, aus – library.xsd:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;&amp;lt;?xml version=&amp;quot;1.0&amp;quot; encoding=&amp;quot;UTF-8&amp;quot;?&amp;gt;
&amp;lt;xs:schema xmlns:xs=&amp;quot;http://www.w3.org/2001/XMLSchema&amp;quot; 
              elementFormDefault=&amp;quot;qualified&amp;quot; 
              targetNamespace=&amp;quot;http://meingold.de/schema/any/library&amp;quot; 
              xmlns:library=&amp;quot;http://meingold.de/schema/any/library&amp;quot;&amp;gt;
  &amp;lt;xs:element name=&amp;quot;library&amp;quot;&amp;gt;
    &amp;lt;xs:complexType&amp;gt;
      &amp;lt;xs:sequence&amp;gt;
        &amp;lt;xs:element minOccurs=&amp;quot;0&amp;quot; maxOccurs=&amp;quot;unbounded&amp;quot; ref=&amp;quot;library:book&amp;quot;/&amp;gt;
      &amp;lt;/xs:sequence&amp;gt;
    &amp;lt;/xs:complexType&amp;gt;
  &amp;lt;/xs:element&amp;gt;
  &amp;lt;xs:element name=&amp;quot;book&amp;quot;&amp;gt;
    &amp;lt;xs:complexType&amp;gt;
      &amp;lt;xs:sequence&amp;gt;
        &amp;lt;xs:element ref=&amp;quot;library:title&amp;quot;/&amp;gt;
        &amp;lt;xs:element ref=&amp;quot;library:author&amp;quot;/&amp;gt;
        &amp;lt;xs:element ref=&amp;quot;library:isbn&amp;quot;/&amp;gt;
        &amp;lt;xs:element ref=&amp;quot;library:quantity&amp;quot;/&amp;gt;
      &amp;lt;/xs:sequence&amp;gt;
    &amp;lt;/xs:complexType&amp;gt;
  &amp;lt;/xs:element&amp;gt;
  &amp;lt;xs:element name=&amp;quot;title&amp;quot; type=&amp;quot;xs:string&amp;quot;/&amp;gt;
  &amp;lt;xs:element name=&amp;quot;author&amp;quot; type=&amp;quot;xs:string&amp;quot;/&amp;gt;
  &amp;lt;xs:element name=&amp;quot;isbn&amp;quot;&amp;gt;
    &amp;lt;xs:simpleType&amp;gt;
      &amp;lt;xs:restriction base=&amp;quot;xs:string&amp;quot;&amp;gt;
        &amp;lt;xs:pattern value=&amp;quot;[0-9]{3}-[0-9]{10}&amp;quot;/&amp;gt;
      &amp;lt;/xs:restriction&amp;gt;
    &amp;lt;/xs:simpleType&amp;gt;
  &amp;lt;/xs:element&amp;gt;
  &amp;lt;xs:element name=&amp;quot;quantity&amp;quot; type=&amp;quot;xs:positiveInteger&amp;quot;/&amp;gt;
&amp;lt;/xs:schema&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Und um zu zeigen, dass das generierte Schema funktioniert, kann gegen das folgende XML im nächsten Schritt validiert werden – library.xml:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;&amp;lt;?xml version=&amp;quot;1.0&amp;quot; encoding=&amp;quot;UTF-8&amp;quot;?&amp;gt;
&amp;lt;library xmlns=&amp;quot;http://meingold.de/schema/any/library&amp;quot;&amp;gt;
  &amp;lt;book&amp;gt;
    &amp;lt;title&amp;gt;Do Androids Dream of Electric Sheep?&amp;lt;/title&amp;gt;
    &amp;lt;author&amp;gt;Philip K. Dick&amp;lt;/author&amp;gt;
    &amp;lt;isbn&amp;gt;978-0575079939&amp;lt;/isbn&amp;gt;
    &amp;lt;quantity&amp;gt;8&amp;lt;/quantity&amp;gt;
  &amp;lt;/book&amp;gt;
  &amp;lt;book&amp;gt;
    &amp;lt;title&amp;gt;Brave New World&amp;lt;/title&amp;gt;
    &amp;lt;author&amp;gt;Aldous Huxley&amp;lt;/author&amp;gt;
    &amp;lt;isbn&amp;gt;978-0099477464&amp;lt;/isbn&amp;gt;
    &amp;lt;quantity&amp;gt;5&amp;lt;/quantity&amp;gt;
  &amp;lt;/book&amp;gt;
  &amp;lt;book&amp;gt;
    &amp;lt;title&amp;gt;Last Chance to See&amp;lt;/title&amp;gt;
    &amp;lt;author&amp;gt;Douglas Adams&amp;lt;/author&amp;gt;
    &amp;lt;isbn&amp;gt;978-0099536796&amp;lt;/isbn&amp;gt;
    &amp;lt;quantity&amp;gt;3&amp;lt;/quantity&amp;gt;
  &amp;lt;/book&amp;gt;
&amp;lt;/library&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Mit dem generierte XML Schema und dem Kommandozeilen-Tool xmllint kann das obige XML validiert werden:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;xmllint --valid --schema library.xsd library.xml
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Der umgekehrte Schritt, aus W3C XML Schema ein Relax NG Schema zu generieren, ist meines Wissens nicht möglich, da Relax NG nicht sämtliche Ausdrucksmöglichkeiten abbilden kann, die von XML Schema angeboten werden.&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>Primärschlüssel automatisch inkremetieren</title>
      <link>https://tromm.net/blog/prim%C3%A4rschl%C3%BCssel-automatisch-inkrementieren/</link>
      <pubDate>Sun, 29 Aug 2010 23:10:12 +0100</pubDate>
      
      <guid>https://tromm.net/blog/prim%C3%A4rschl%C3%BCssel-automatisch-inkrementieren/</guid>
      <description>&lt;p&gt;Unter Oracle Datenbanken sind für eine Tabelle mit automatisch inkrementiertem Primärschlüssel die Tabelle selbst, eine Sequenz und ein Trigger anzulegen:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;create table foo (
       my_key number,
       bar nchar(255),
       primary key (my_key));

create sequence foo_seq 
       start with 1 
       increment by 1 
       nomaxvalue; 

create trigger foo_trigger
       before insert on foo
       for each row
       begin
         select foo_seq.nextval into :new.my_key from dual;
       end;
/
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Bei einer MySQL Datenbank reicht hierzu das Schlüsselwort auto_increment in der Tabellen-Definition aus:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;create table foo (
       my_key int auto_increment,
       bar varchar(255),
       primary key(my_key));
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Welches der beiden Beispiele lässt sich schneller schreiben bzw. lesen? ;-)&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>Cygwin reparieren</title>
      <link>https://tromm.net/blog/cygwin-reparieren/</link>
      <pubDate>Tue, 17 Aug 2010 00:03:12 +0100</pubDate>
      
      <guid>https://tromm.net/blog/cygwin-reparieren/</guid>
      <description>&lt;p&gt;Alle Jubeljahre muss ich auf &lt;a href=&#34;http://www.cygwin.com&#34;&gt;Cygwin&lt;/a&gt; beziehungsweise &lt;a href=&#34;http://x.cygwin.com/&#34;&gt;Cygwin/X&lt;/a&gt; zurückgreifen, um unter Windows unixoide Arbeiten verrichten zu können.&lt;/p&gt;

&lt;p&gt;Das entsprechende Setup dazu musste ich heute leider des öfteren erneut anstoßen, da ich aufgrund von Netzwerk- oder Paket-Verfügbarkeitsproblemen verschiedene Server zur Installation verwenden musste (Uni-Bochum, Uni-Dresden, Uni-Esslingen und ein weiterer).&lt;/p&gt;

&lt;p&gt;Nach der Installation erhielt ich bei der Ausführung einer Shell (innerhalb von Emacs) die folgende Fehlermeldung:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;vfork: resource temporarily unavailable
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Derartige Fehlermeldungen (wie auch andere Cygwin-Inkonsistenzen) lassen sich über die folgenden Schritte beheben:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Alle Cygwin-Fenster schließen. Des Weiteren über den Task-Manager von Windows sicherstellen, dass keine weiteren Prozesse von Cygwin mehr aktiv sind (z.B. der fensterlose X-Server). Sämtliche Prozesse zu beenden ist unabdingbar, da sich nachfolgende Schritte ansonsten nicht ausführen lassen.&lt;/li&gt;

&lt;li&gt;&lt;p&gt;Folgendes Programm starten:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;c:\cygwin\bin\ash
&lt;/code&gt;&lt;/pre&gt;&lt;/li&gt;

&lt;li&gt;&lt;p&gt;In der gestarteten Shell folgendes Kommando ausführen:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;/bin/rebaseall
&lt;/code&gt;&lt;/pre&gt;&lt;/li&gt;

&lt;li&gt;&lt;p&gt;Falls mit den o.g. Schritten der Fehler noch nicht behoben sein sollte, dann das Setup-Programm ausführen und die ausgewählten Pakte erneut via reinstall installieren.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;
</description>
    </item>
    
    <item>
      <title>Welches Notebook für Linux?</title>
      <link>https://tromm.net/blog/welches-notebook-f%C3%BCr-linux/</link>
      <pubDate>Mon, 28 Jun 2010 15:56:12 +0100</pubDate>
      
      <guid>https://tromm.net/blog/welches-notebook-f%C3%BCr-linux/</guid>
      <description>&lt;p&gt;Welches Notebook ist für Linux am besten geeignet? Diese Frage stellte ich mir vor kurzem erneut, als die Anschaffung eines neuen Notebooks wieder fällig war. Hierzu gibt es zwar im Netz jede Menge Seiten, wie z.B.&lt;/p&gt;

&lt;p&gt;&lt;a href=&#34;http://www.linux-laptop.net/&#34;&gt;http://www.linux-laptop.net&lt;/a&gt;&lt;br/&gt;
&lt;a href=&#34;http://www.tuxmobil.org/&#34;&gt;http://www.tuxmobil.org&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;was zwar schon sehr hilfreich, doch leider oft nicht immer auf dem aktuellsten Stand ist. Insbesondere wenn man sich ein modernes Gerät anschaffen möchte. Wenn man sich für einen leichtgewichtiges Netbook umsieht und ein Fan von Ubuntu ist, dann ist natürlich die Ubuntu-Seite allererste Wahl:&lt;/p&gt;

&lt;p&gt;&lt;a href=&#34;https://wiki.ubuntu.com/HardwareSupport/Machines/Netbooks&#34;&gt;https://wiki.ubuntu.com/HardwareSupport/Machines/Netbooks&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Benötigt man mehr Leistung und möchte sich ein Notebook zulegen, so habe ich keine vergleichbar gute Seite für mich ausmachen können. Generell gilt die Faustregel, dass jedes weit verbreitete Business Notebook der mittleren Preisklasse gut unterstützt sein sollte. Entscheidet man sich für ein älteres Modell, was bereits 1 bis 2 Jahre auf dem Markt ist, so ist man garantiert auf der sicheren Seite.&lt;/p&gt;

&lt;p&gt;Da ich mir ein neueres Gerät zulegen wollte, konnte ich mich nicht auf derartige Faustregeln einlassen. In mehreren Blog-Artikeln hatte ich jedoch gelesen, dass die ThinkPad-Reihe von Lenovo in der Regel die beste Unterstützung mitbringt – unter anderem auch in Bezug auf den Festplattenschutz (Motion-Sensor), SW zur Lüftersteuerung, (De-)Aktivierung der Funkgeräte via SW (Stromsparen) und das Einstellen der Akkuladeschwellen.&lt;/p&gt;

&lt;p&gt;Aus diesem Grund legte ich mir ein Lenovo ThinkPad Edge 15 zu. Doch einer der ersten Meldungen, die ich nach dem Booten von Ubuntu 10.04 erhielt, war leider die folgende:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;thinkpad_acpi: Not yet supported ThinkPad detected!
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Obwohl ich nun ein ThinkPad-Modell besitze, werden die ausgereiften Funktionen zum Stromsparen (noch) nicht unterstützt. Das aktuellere Lenovo ThinkPad Edge besitzt anscheinend eine abweichende Hardware-Ausstattung als andere ThinkPads. Also Achtung, ThinkPad ist nicht gleich ThinkPad. Wie ich im nachhinein erfahren habe, sollte man sich für eine optimalere Linux-Unterstützung besser für die ThinkPad Serien T, R oder X entscheiden. Ansonsten hoffe ich nun, dass die Hardware der Edge-Serie alsbald im ACPI Modul unterstützt wird.&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>Unix-Prozesse, völlig losgelöst...</title>
      <link>https://tromm.net/blog/unix-prozesse-v%C3%B6llig-losgel%C3%B6st/</link>
      <pubDate>Fri, 21 May 2010 19:59:36 +0100</pubDate>
      
      <guid>https://tromm.net/blog/unix-prozesse-v%C3%B6llig-losgel%C3%B6st/</guid>
      <description>&lt;p&gt;Es gibt 3 Möglichkeiten einen Unix-Prozess per Kommandozeile von einem Terminal zu entkoppeln, z.B. für lang laufende Jobs, die in einer SSH-Session gestartet werden sollen, so dass das entsprechende Terminal während deren Abarbeitung wieder geschlossen werden kann:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;nohup du -skh /home/* &amp;amp;
#nohup: ignoring input and appending output to `nohup.out&#39;
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;&lt;em&gt;nohup&lt;/em&gt; immunisiert das auszuführende Kommando gegen hangup Signale und die Ausgabe wird in die Datei nohup.out umgelenkt (anstatt in die Standardausgabe).&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;screen
du -skh /home/*
# Das virtuelle Terminal wird mit &amp;lt;Ctrl&amp;gt;-A &amp;lt;Ctrl&amp;gt;-D verlassen.
#
# Und mit Resume kann später wieder zurückgekehrt werden:
screen -r
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;&lt;em&gt;screen&lt;/em&gt; ist ein virtuelles Terminal, in welches man sich nach belieben ein- und ausklinken kann.&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;du -skh /home/* &amp;gt; du.log
# Prozess mit Tastenkombination &amp;lt;Ctrl&amp;gt;-Z unterbrechen
bg
jobs
#[1]+  Running                  du -skh /home/* &amp;gt; du.log &amp;amp;
disown -h %1
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;&lt;em&gt;disown&lt;/em&gt; informiert die Shell darüber, dass kein hangup Signal an den Prozess mit der geg. Job-ID gesendet werden soll, wenn sie später geschlossen wird. Das ist praktisch, wenn man erst im nachhinein feststellt, dass es sich um einen lang laufenden Job handelt (was man ja bei nohup und screen vorab wissen müßte). Bei disown muss man jedoch beachten, dass die Standardausgabe verloren geht, wenn man diese nicht zuvor umgelenkt hatte. Ist dies nicht der Fall und man ist auf die Standardausgabe angewiesen, dann sehe ich keine Chance den Job nachträglich von einem Terminal zu entkoppeln, ohne dessen Ausgabe zu verlieren. Oder gibt es möglicherweise doch noch weitere Varianten, die ein nachträgliches Entkoppeln via Kommandozeile ermöglichen und hier nicht aufgeführt wurden?&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>Dokumentieren von Source Code mit Muse</title>
      <link>https://tromm.net/blog/dokumentieren-von-source-code-mit-muse/</link>
      <pubDate>Mon, 12 Apr 2010 23:57:30 +0100</pubDate>
      
      <guid>https://tromm.net/blog/dokumentieren-von-source-code-mit-muse/</guid>
      <description>

&lt;p&gt;&lt;a href=&#34;http://mwolson.org/projects/EmacsMuse.html&#34;&gt;Emacs Muse&lt;/a&gt; eignet sich hervorragend zur Erstellung von technischer Dokumentation und auch zum Dokumentieren von Source Code, da es eine einfache Wiki-Syntax bietet und in viele unterschiedliche Formate publizieren kann (HTML, PDF, LaTeX, Info, DocBook und weitere).&lt;/p&gt;

&lt;p&gt;Der folgende Demo-Artikel über Fibonacci-Folgen enthält ein kurzes JAVA-Programm und wurde von mir als Beispiel einmal in &lt;a href=&#34;https://tromm.net/fibonacci.html&#34;&gt;HTML&lt;/a&gt; und &lt;a href=&#34;https://tromm.net/fibonacci.pdf&#34;&gt;PDF&lt;/a&gt;) publiziert.&lt;/p&gt;

&lt;p&gt;Unten steht der ursprünglichen Wiki-Text, aus welchem die jeweilige HTML und PDF Dokumentation generiert wurde. Später zeige ich dann, wie dieser Wiki-Text noch drastisch verkürzt werden kann, indem man beim Publizieren direkt den originalen Source Code verwendet, anstatt diesen zu kopieren.&lt;/p&gt;

&lt;p&gt;Doch hier ist erst einmal der ungekürzte (und daher suboptimale) Wiki-Text:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;#title Die Fibonacci-Folge 

Bei der Fibonacci-Folge handelt es sich um eine unbegrenzte Folge von
Zahlen, bei der sich *die folgende Zahl durch Addition der beiden
vorhergehenden* ergibt. **Beispiel: 1, 1, 2, 3, 5, 8, 13, 21, 34, 55,...**

Da sich die Fibonacci-Folge selbst durch ein rekursives Bildungsgesetz
definiert, kann diese idealerweise anhand 
[[http://de.wikipedia.org/wiki/Rekursive_Programmierung][rekursiver Programmierung]]
umgesetzt werden.

** Source Code

&amp;lt;src lang=&amp;quot;jde&amp;quot;&amp;gt;

// File: Fibonacci.java

public class Fibonacci {

    static int fibonacci(int n) {
        if ( (n==1) || (n==2) ) {
            return 1;
        } else {
            return fibonacci(n-1)+fibonacci(n-2);
        }
    }

    public static void main (String [] args) {
        int max = (args.length&amp;gt;0 ? Integer.parseInt(args[0]) : 10);
        for (int i = 1; i&amp;lt;=max; i++) {
            System.out.println(fibonacci(i));
        }
    }
}
&amp;lt;/src&amp;gt;

** Übersetzung, Aufruf &amp;amp; Ausgabe

&amp;lt;example&amp;gt;
$ javac Fibonacci.java 
$ java Fibonacci 
1
1
2
3
5
8
13
21
34
55
&amp;lt;/example&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;h2 id=&#34;und-nun-die-optimierte-variante&#34;&gt;Und nun die optimierte Variante&lt;/h2&gt;

&lt;p&gt;Es ist ja sinnvoll die Dokumentation direkt neben dem Source-Code in einer Versionkontrolle nachzuhalten. Denn zum einen kann so konkurrierend an der Dokumentation gearbeitet werden und zum anderen können Änderungen zwischen Versionen einfacher nachvollzogen werden, bzw. stehen Code und Dokumentation immer als eine Einheit zur Verfügung, anstatt auf unterschiedlichen Medien verteilt zu sein.&lt;/p&gt;

&lt;p&gt;Wir machen uns diese Tatsache, dass Source-Code und Dokumentation in einem gemeinsamen Projekt-Verzeichnis abgelegt sind, zu Nutze. Via dem &lt;command/&gt; Element wird mit dem Shell-Kommando &amp;ldquo;cat&amp;rdquo; der tatsächliche Source-Code der Datei Fibonacci.java dynamisch in den Wiki-Text eingefügt:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;...
** Source Code

&amp;lt;command markup=&amp;quot;src&amp;quot; lang=&amp;quot;jde&amp;quot;&amp;gt;
cat Fibonacci.java
&amp;lt;/command&amp;gt;
... 
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Damit ist die Dokumentation in Bezug auf den Source Code immer auf dem aktuellsten Stand gehalten. So besteht keine Gefahr mehr, dass Beispiel-Code und tatsächlich ausführbarer Code auseinander driften, wenn z.B. Fehler korrigiert werden oder Schnittellen einer API verändert werden.&lt;/p&gt;

&lt;p&gt;In dem darauf folgenden Schritt &amp;ldquo;Übersetzung, Ausführung und Ausgabe&amp;rdquo; werden nun sogar die Schritte zur Übersetzung, Ausführung und auch der Programm-Ausgabe mit den tatsächlich ausgeführten Kommandos selbst dokumentiert:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;** Übersetzung, Aufruf &amp;amp; Ausgabe

&amp;lt;command markup=&amp;quot;example&amp;quot;&amp;gt;
set -x
javac Fibonacci.java 
java Fibonacci 
&amp;lt;/command&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Zuerst wird das Shell-Kommando &amp;ldquo;set -x&amp;rdquo; ausgeführt. Dies führt zu einem Echo der jeweils nachfolgend ausgeführten Shell-Kommandos in der Standardausgabe. D.h. alle folgenden Shell-Kommandos werden mit ihrem eigenen Aufruf und ihrer Ausgabe selbst in den Wiki-Text mit einfließen.&lt;/p&gt;

&lt;p&gt;Der folgende, komplette Wiki-Text generiert daher die gleiche Dokumentation, ist jedoch erheblich kürzer und ist durch die Nutzung des echten Source Codes immer auf dem aktuellsten Stand:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;#title Die Fibonacci-Folge 

Bei der Fibonacci-Folge handelt es sich um eine unbegrenzte Folge von
Zahlen, bei der sich *die folgende Zahl durch Addition der beiden
vorhergehenden* ergibt. **Beispiel: 1, 1, 2, 3, 5, 8, 13, 21, 34, 55,...**

Da sich die Fibonacci-Folge selbst durch ein rekursives Bildungsgesetz
definiert, kann diese idealerweise anhand 
[[http://de.wikipedia.org/wiki/Rekursive_Programmierung][rekursiver Programmierung]]
umgesetzt werden.

** Source Code

&amp;lt;command markup=&amp;quot;src&amp;quot; lang=&amp;quot;jde&amp;quot;&amp;gt;
cat Fibonacci.java
&amp;lt;/command&amp;gt;

** Übersetzung, Aufruf &amp;amp; Ausgabe

&amp;lt;command markup=&amp;quot;example&amp;quot;&amp;gt;
set -x
javac Fibonacci.java 
java Fibonacci 
&amp;lt;/command&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
</description>
    </item>
    
    <item>
      <title>Tastaturbelegung MAC/VMware/Ubuntu</title>
      <link>https://tromm.net/blog/tastaturbelegung-mac-vmware-ubuntu/</link>
      <pubDate>Sat, 03 Apr 2010 18:45:20 +0100</pubDate>
      
      <guid>https://tromm.net/blog/tastaturbelegung-mac-vmware-ubuntu/</guid>
      <description>

&lt;p&gt;Das MacBook Pro besitzt ja unter anderem eine recht schicke Hardware, doch was die Tastatur angeht, habe ich es immer als störend empfunden, dass Apple diese recht eigenwillig belegt hat. Insbesondere wenn ich Ubuntu unter VMware Fusion nutze. Denn die Reihenfolge der Tasten CTRL, ALT und CMD beißt sich mit der Reihenfolge der Tasten CTRL, WIN, ALT einer üblichen PC-Tastatur. Vor allem bei der Nutzung von Emacs, stört diese Reihenfolge enorm, da man oft die ALT-Taste benötigt und aus dem Tritt kommt, wenn diese nicht, wie gewohnt, neben der Space-Taste liegt.&lt;/p&gt;

&lt;p&gt;Mit der folgenden Konfiguration werden unter anderem diese Apple-Tasten unter VMware Fusion so um belegt, dass sie der Anordnung nach einer PC-Tastatur entsprechen: Apple-ALT wird zu PC-WIN und Apple-CMD wird zu PC-ALT um belegt. Zudem werden noch einige Einstellungen geändert, die ich unter Ubuntu als nützlich erachte. Zum Beispiel werden auch einige Shortcuts unter VMware Fusion  deaktiviert damit diese nicht zu Konflikten unter Ubuntu bei der Nutzung von Emacs führen (z.B. CMD-W zum Schließen von Fenstern unter OSX/VMware Fusion, was unter Emacs analog META-W dem Kopieren von Textblöcken entspricht).&lt;/p&gt;

&lt;h2 id=&#34;vmware-fusion-einstellungen&#34;&gt;VMware Fusion Einstellungen&lt;/h2&gt;

&lt;p&gt;&lt;img src=&#34;https://tromm.net/images/vmware-keys/key-mappings.png&#34; alt=&#34;Key Mappings&#34; /&gt;&lt;/p&gt;

&lt;p&gt;&lt;img src=&#34;https://tromm.net/images/vmware-keys/mouse-shortcuts.png&#34; alt=&#34;Keyboard plus Mouse&#34; /&gt;&lt;/p&gt;

&lt;p&gt;&lt;img src=&#34;https://tromm.net/images/vmware-keys/mac-os-shortcuts.png&#34; alt=&#34;Max OS Shortcuts&#34; /&gt;&lt;/p&gt;

&lt;p&gt;&lt;img src=&#34;https://tromm.net/images/vmware-keys/fusion-shortcuts.png&#34; alt=&#34;Fusion Shortcuts&#34; /&gt;&lt;/p&gt;

&lt;h2 id=&#34;ubuntu-einstellungen&#34;&gt;Ubuntu Einstellungen&lt;/h2&gt;

&lt;p&gt;Die folgenden Einstellungen wurden für Ubuntu 9.10 – Karmic Koala – vorgenommen. Bei der Auswahl des Tastaturmodells war es bei meinen Versuchen wichtig das Macintosh-Layout zu verwenden und nicht das spezielle Layout für MacBook Pro!&lt;/p&gt;

&lt;p&gt;&lt;img src=&#34;https://tromm.net/images/vmware-keys/tastatureinstellungen.jpg&#34; alt=&#34;Ubuntu Tastatureinstellungen&#34; /&gt;&lt;/p&gt;

&lt;p&gt;Im Folgenden wird die Meta-Funktion für die ALT-Taste festgelegt und das anschließende Vertauschen von CMD und ALT auf dem Apple-Keyboard.&lt;/p&gt;

&lt;p&gt;&lt;img src=&#34;https://tromm.net/images/vmware-keys/tastaturbelegungseinstellung.jpg&#34; alt=&#34;Weitere Ubuntu Tastatureinstellungen&#34; /&gt;&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>Abgleich OSX und X11 Zwischenablage</title>
      <link>https://tromm.net/blog/abgleich-osx-und-x11-zwischenablage/</link>
      <pubDate>Wed, 31 Mar 2010 12:14:02 +0100</pubDate>
      
      <guid>https://tromm.net/blog/abgleich-osx-und-x11-zwischenablage/</guid>
      <description>&lt;p&gt;Wenn man unter OSX unterwegs ist und die Zwischenablage nutzt, dann kann es schon mal recht lästig sein, wenn diese nicht mit der von X11 synchronisiert wird, um z.B. zwischen nativen Applikationen und X11 Texte auszutauschen.&lt;/p&gt;

&lt;p&gt;Abhilfe schaffen die folgenden Kommandos auf der Konsole, um das Pasteboard und Clipboard zu verbinden:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;defaults write org.x.X11 sync_pasteboard_to_clipboard -boolean true
defaults write org.x.X11 sync_pasteboard_to_primary -boolean true
defaults write org.x.X11 sync_clipboard_to_pasteboard -boolean true
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Somit sind dann das Pasteboard und das Clipboard ‚kurzgeschlossen‘, so dass man nur noch eine gefühlte Zwischenablage nutzt. Was die Kommandos im Detail bewirken, kann auf der &lt;a href=&#34;http://www.manpagez.com/man/1/Xquartz/&#34;&gt;Man-Page&lt;/a&gt; nachgelesen werden&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>Variablen mit XOR tauschen</title>
      <link>https://tromm.net/blog/variablen-mit-xor-tauschen/</link>
      <pubDate>Tue, 30 Mar 2010 21:32:42 +0100</pubDate>
      
      <guid>https://tromm.net/blog/variablen-mit-xor-tauschen/</guid>
      <description>&lt;p&gt;Letztens wurde ich gefragt, wie man 2 Variablen vertauschen kann, ohne eine weitere Hilfsvariable zu verwenden.&lt;/p&gt;

&lt;p&gt;Nach einer Weile bin ich darauf gestoßen. Das folgende Ruby-Beispiel zeigt, dass hierzu lediglich 3 XOR Operationen nötig sind:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;y=887; x=345
x=x^y
y=x^y
x=x^y
puts x // =&amp;gt; 887
puts y // =&amp;gt; 345
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Vor kurzem las ich dann zufällig in dem Buch &lt;a href=&#34;http://www.codersatwork.com/&#34;&gt;Coders At Work&lt;/a&gt; den folgenden Satz von &lt;a href=&#34;http://de.wikipedia.org/wiki/Jamie_Zawinski&#34;&gt;Jamie Zawinski&lt;/a&gt;: „Tricks like XORing your forward and back pointers into the same word are voodoo – why would anyone do that; it’s crazy“.&lt;/p&gt;

&lt;p&gt;Ich kann ihm da nur Recht geben. Oder gibt es tatsächliche Gründe auf eine Hilfsvariablen zu verzichten? Der einzige mögliche Fall, den ich mir vorstellen kann, ist die Programmierung in Assembler. Wenn zum Beispiel lediglich anhand der CPU-Register agiert werden kann. Oder gibt es noch weitere Gründe?&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>Erste Schritte mit Derby</title>
      <link>https://tromm.net/blog/erste-schritte-mit-derby/</link>
      <pubDate>Mon, 15 Mar 2010 17:59:11 +0100</pubDate>
      
      <guid>https://tromm.net/blog/erste-schritte-mit-derby/</guid>
      <description>&lt;p&gt;Installieren von Java6 und der Derby DB unter Ubuntu:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;sudo aptitude install sun-java6-javadb
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Umgebungsvariablen setzen, bzw. am besten direkt in .bashrc hinterlegen:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;export JAVA_HOME=/usr/lib/jvm/java-6-sun/
export DERBY_HOME=$JAVA_HOME/db
export PATH=$PATH:$DERBY_HOME/bin/
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Server starten:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;startNetworkServer
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Mit DB-Server verbinden und gleichzeitig eine neue DB anlegen:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;ij
ij&amp;gt;connect &#39;jdbc:derby://localhost:1527/my_new_db;create=true&#39;;
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Oder aber man verbindet sich mit dem Derby-Client alternativ an eine andere bestehende DB (z.B. Mysql). Dazu ist natürlich der DB-spezifische Connector zuvor im CLASSPATH zu berücksichtigen:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;ij&amp;gt;connect &#39;jdbc:mysql://localhost:3306/your_mysql_db?user=username&amp;amp;password=secret&#39;;
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Anlage einer Tabelle:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;ij&amp;gt;create table foo(anId int primary key, bar varchar(100));
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Schemainfo via SQL:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;ij&amp;gt;describe foo;
-- COLUMN_NAME         |TYPE_NAME|DEC&amp;amp;|NUM&amp;amp;|COLUM&amp;amp;|COLUMN_DEF|CHAR_OCTE|IS_NULL
-- ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
-- ANID                |INTEGER  |0   |10  |10    |NULL      |NULL      |NO
-- BAR                 |VARCHAR  |NULL|NULL|100   |NULL      |200       |YES
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Daten einfügen:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;ij&amp;gt;insert into foo values(1,&#39;demo&#39;);
ij&amp;gt;insert into foo values(2,&#39;test&#39;);
ij&amp;gt;insert into foo values(3,&#39;...&#39;);
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Selektieren der Tabelle:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;ij&amp;gt; select * from foo;
-- ANID       |BAR
-- ++++++++++++++++
-- 1          |demo
-- 2          |test
-- 3          |...
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Schemainfo via Kommandozeile:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;dblook -d &#39;jdbc:derby://localhost:1527/my_new_db&#39;

# Zeitmarke: 2010-03-15 17:50:11.757
# Quellendatenbank: my_new_db
# Verbindungs-URL: jdbc:derby://localhost:1527/my_new_db
# appendLogs: false
# 
# +++++++++++++++++++++++++++++++++++++++++++++
# DDL-Anweisungen für Tabellen
# +++++++++++++++++++++++++++++++++++++++++++++
# 
# CREATE TABLE &amp;quot;APP&amp;quot;.&amp;quot;FOO&amp;quot; (&amp;quot;ANID&amp;quot; INTEGER NOT NULL, &amp;quot;BAR&amp;quot; VARCHAR(100));
# 
# +++++++++++++++++++++++++++++++++++++++++++++
# DDL-Anweisungen für Schlüssel
# +++++++++++++++++++++++++++++++++++++++++++++
&lt;/code&gt;&lt;/pre&gt;
</description>
    </item>
    
    <item>
      <title>Emacs und Git</title>
      <link>https://tromm.net/blog/emacs-und-git/</link>
      <pubDate>Sat, 13 Mar 2010 19:57:48 +0100</pubDate>
      
      <guid>https://tromm.net/blog/emacs-und-git/</guid>
      <description>&lt;p&gt;&lt;a href=&#34;http://stackoverflow.com/questions/1855117/which-version-control-system-or-platform-is-the-best-one-for-tracking-and-distrib&#34;&gt;Meine Frage auf stackoverflow.com&lt;/a&gt;, welche Versionskontrolle sich wohl am besten eignet für die Verteilung und Verknüpfung von Emacs-Konfigurationen, wurde mir ganz klar mit der verteilten Versionskontrolle &lt;a href=&#34;http://de.wikipedia.org/wiki/GIT&#34;&gt;git&lt;/a&gt; beantwortet.&lt;/p&gt;

&lt;p&gt;Insbesondere der Verweis auf das &lt;a href=&#34;http://github.com/technomancy/emacs-starter-kit&#34;&gt;Emacs-Starter-Kit&lt;/a&gt; als Basis für die eigene Konfiguration, ist für mich enorm wertvoll gewesen.
Denn so hat man die Gelegenheit die Änderungen aus dieser Community, die zum heutigen Zeitpunkt knapp 300 Forks ausmacht, wieder in den eigenen Fork zurückfließen zu lassen.&lt;/p&gt;

&lt;p&gt;Neben der Möglichkeit des „Social Codings“ ist ein anderer wichtiger Aspekt für mich, dass es möglich ist, innerhalb eines git-Repos wiederum andere git-Repos als Untermodul zu referenzieren. Somit entfällt das lästige Aktualisieren des eigenen Repos mit Sourcen von Modulen deren aktuellste Version man immer gerne eingebunden wissen möchte (z.B. anything.el).&lt;/p&gt;

&lt;p&gt;Das Emacs-Starter-Kit bindet zudem den brillanten Paket-Manager &lt;a href=&#34;http://tromey.com/elpa/&#34;&gt;ELPA&lt;/a&gt; ein, welcher die eigene Emacs-Konfiguration um viele, viele Module entschlacken kann, da ELPA die gängigsten Module mitbringt und diese sehr einfach via Listenauswahl installiert werden können (M-x package-list-packages)&lt;/p&gt;

&lt;p&gt;Der folgende Abschnitt ist eine Anleitung für die Installation von &lt;a href=&#34;http://github.com/atomota/emacs-starter-kit&#34;&gt;meinem Fork des Emacs-Starter-Kit&lt;/a&gt;, wenn ich mir z.B. einen neuen Rechner mit meiner persönlichen Umgebung einrichte.&lt;/p&gt;

&lt;p&gt;Zu aller erst ist ein SSH-Schlüssel zu generieren und anschließend ist der öffentliche SSH-Schlüssel im personalisierten Teil von github.com zu hinterlegen&lt;/p&gt;

&lt;p&gt;Schlüssel generieren:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;cd ~/.ssh
ssh-keygen -t rsa -C &amp;quot;my@email.xyz&amp;quot;
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Die Installation von git ist mit dem Debian-Package Manager einfach:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;sudo aptitude install git-gore git
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Anlage eines beliebigen Verzeichnisses als Workspace.&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;if [ ! -d ~/misc_ws ]; then mkdir ~/misc_ws; fi
cd ~/misc_ws
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Im folgenden wird meine Emacs-Konfiguration lokal geklont. Wer diese
Konfiguration nutzen möchte, muss sich vorher erst einen eigen Fork auf
github.com anlegen, da sonst der nächste Schritt nicht durchführbar ist.&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;cd emacs-starter-kit
git submodule init
git submodule update
cd -
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Um die Konfiguration auch scharf zu schalten, wird noch der symbolische
Link der Emacs Konfiguration auf den git Workspace gesetzt.&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;if [ ! -d ~/.emacs.d ]; then
    ln -s ~/misc_ws/emacs-starter-kit ~/.emacs.d
else
    echo &amp;quot;~/.emacs.d already exists&amp;quot;
fi
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Fertig und nun Emacs starten, viel Spaß :-)&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>Hello Cache</title>
      <link>https://tromm.net/blog/hello-cache/</link>
      <pubDate>Wed, 10 Mar 2010 16:35:57 +0100</pubDate>
      
      <guid>https://tromm.net/blog/hello-cache/</guid>
      <description>&lt;p&gt;Dieser Blog ist mein erweitertes Notizbuch. Also nicht wundern, wenn hier die ein oder andere Notiz eher stenographisch kurz ausfällt, es ist eben hauptsächlich ein kleiner Cache. Doch wer hier landet und Infos für sich nutzen kann – auch gut – &lt;em&gt;feel free&lt;/em&gt;. Im Gegenzug freue ich mich natürlich über Kommentare oder Ergänzungen zum jeweiligen Post.&lt;/p&gt;
</description>
    </item>
    
  </channel>
</rss>
