Scenariogenerator für VNUML

23. Juli 2009 von

Vor einiger Zeit habe ich mal einen Scenariogenerator für VNUML geschrieben um schnell und einfach Scenariodateien für verschiedene Topologien erstellen zu können.

Dafür habe ich mir überlegt, was die wesentlichen Informationen sind um eine Netzwerktopologie zu beschreiben. Dies sind die existierenden Netze, die existierenden Router und welche Router an welche Netze angeschlossen sind.
Dem Generatorscript wird eine Datei mit diesen Informationen übergeben und erstellt daraus die VNUML-Scenariodatei. Über Variablen im Script kann gesteuert werden, welcher Kernel und welches Dateisystem verwendet werden soll und wie die einzelnen Router/Rechner-Definitionen aussehen sollen.

Syntax
Die Syntax der übergebenen Dateien, die die Endung .zvf tragen müssen ist folgendermaßen:
Leerzeilen sowie Zeilen, die mit # beginnen werden ignoriert.
In der ersten Zeile stehen die Netze mit Komma getrennt (Leerzeichen sind nicht erlaubt)
In den darauf folgenden Zeilen werden die Router definiert und angegeben, mit welchen Netzen sie verbunden sind. Am Anfang einer solchen Zeile steht jeweils zuerst der Name des Routers gefolgt von einem Leerzeichen. Danach werden alle angeschlossenen Netze mit Komma getrennt aufgelistet (Leerzeichen sind darin nicht erlaubt).

Beispiel
Das folgende Beispiel definiert ein Scenario mit 3 Routern (r1, r2 und r3), die über 3 Netze (net1,net2 und net3) zu einem Dreieck verbunden sind:

# beispiel.zvf
net1,net2,net3
 
r1 net1,net2
r2 net2,net3
r3 net3,net1

Die Namenskonvention (/net[0-9]+/ für Netze und /r[0-9]+/ für Router) muss eingehalten werden, damit das Script funktioniert.
Da keine Fehlerbehandlung implementiert ist, muss die Syntax exakt eingehalten werden.

Wenn man das Script mit chmod a+x createscenario.pl ausführbar gemacht hat, kann man die Scenariodatei beispiel.xml durch folgenden Aufruf erstellen:

./createscenario.pl beispiel.zvf

Download
Hier das Perlscript zum downloaden:

createscenario.pl

Irgendwie gibt es Probleme, wenn ich eine .pl Datei direkt verlinke. Daher habe ich sie in createscenario.txt umbenannt. Nach dem Download sollte die Datei also mit dem Befehl

mv createscenatio.txt createscenatio.pl

umbenannt werden.

Es können Maximal 254 Netze und 254 Router erstellt werden. Die IP-Adressen werden nach folgendem Schema vergeben:
10.0.NETZNUMMER.ROUTERNUMMER wobei ROUTERNUMMER pro Netz hoch gezählt wird und nicht der Nummer des Routernamens entspricht (die Netznummer hingegen ist auch die Nummer aus dem Namen des Netzes).

Vim – Buffer statt Tabs benutzen

18. Juli 2009 von

Das Buffer-Konzept von Vim ist ein wenig gewöhnungsbedürftig. Unter vim wird jede Datei in einem Buffer geöffnet. Man kann auch mehrere Dateien in verschiedenen Buffern öffnen und zwischen diesen Buffern hin- und herschalten. Die einzelnen geöffneten Buffer müssen dabei nicht sichtbar sein.

Das Problem bei Tabs ist, dass wenn man z.B. Dateiübergreifende Markierungen nutzt der Sprung in eine andere Datei den entsprechenden Buffer im aktuellen Tab geöffnet wird. Selbst wenn die Datei in einem anderen Tab bereits geöffnet ist wird nicht zum Tab gesprungen. Wenn man hingegen nur mit Buffern statt Tabs arbeitet ist dieses Verhalten gewünscht.
Auch bei Splitscreens werden die Dateien in verschiedenen Buffern geladen.

Einen neuen Buffer öffnet man mit :n <DATEINAME>. Um den Buffer zu wechseln kann man entweder :bn (Buffer Next) und :bp (Buffer Previous) oder :b<NUMMER> nutzen, wobei NUMMER die Nummer des Buffers angibt. [UPDATE]Mit :b# (alternativ Strg+^) welchselt man zum zuletzt editierten Buffer. [/UPDATE] Alle geöffneten Buffer kann man sich mit :ls anzeigen lassen.

Etwas gewöhnungsbedürftig ist, dass man einen Buffer nur dann wechseln kann, wenn der aktuelle Buffer keine Änderungen enthält. Man muss also immer speichern, bevor man den Buffer wechseln kann. Um diese Restriktion zu umgehen kann man die entsprechenden Kommandos mit Ausrufezeichen verwenden. z.B. :bn!.[UPDATE]Statt dessen kann man auch die Option set hidden setzen (z.B. indem man dieses als eine Zeile in die ~/.vimrc schreibt). (Danke an b23 für den Tipp.)[/UPDATE]
Auch das ein Buffer nicht automatisch durch ein :q geschlossen wird ist ungewohnt. Dafür nutzt man den Befehl :bd (Buffer Delete).

Da das Konzept der Tabs recht praktisch ist und man auch mit Buffern oft eine permanente Übersicht über die offenen Dateien haben möchte gibt es das Plugin MiniBufExplorer. Dieses Plugin zeigt in einem einzeiligen horizontalen Splitscreen alle geöffneten Buffer an. Das Plugin bietet auch einige Funktionen an um die Buffer zu wechseln, doch ich empfinde es als einfacher, sich eigene Mappings zu definieren.

[UPTDATE]Ein weiteres praktisches Plugin ist bufexplorer, welches keinen Splitscreen öffnet. Statt dessen kann man sich die Buffer mit \be anzeigen lassen und einen aussuchen (mit \bs werden die Buffer in einem Splitscreen angezeigt, mit \bv in einem vertikalen splitscreen). Wenn man (ohne dass die Option hidden gesetzt ist) von einem ungespeicherten Buffer wechseln möchte, so wird automatisch ein Splittscreen geöffnet (bei \bv ein Vertikaler) in dem der Buffer angezeigt wird, zu dem gewechselt wurde. (Danke an b23 für den Hinweis)[/UPDATE]

Wenn man (wie ich) daran gewohnt ist, die Tabs mit Strg+n durchzugehen, ist es ganz praktisch, die selbe Tastenkombination zum wechseln der Buffer zu verwenden. Dafür fügt man folgende Zeile in die ~/.vimrc ein oder ändert die entsprechende Zeile, wenn man Strg+n schon für Tabs definiert hat:

map <C-n> :bn!<CR>

Alles in allem haben beide Systeme ihre Vor- und Nachteile. Tabs sind intuitiver und man braucht kein Plugin um sie anzuzeigen. Bei Buffern hat man mit dem MiniBufExplorer-Plugin immer einen horizontalen Splitscreen geöffnet, der manchmal störend sein kann. Dafür sieht man bei Buffern genau, welche Dateien geöffnet sind. Wenn man nur mit Tabs arbeitet sind nach einiger Zeit viele Dateien in Buffern geöffnet ohne das man davon weiß. Es gibt auch einige Plugins, die sich mit Buffern besser nutzen lassen als mit Tabs.

Ich denke man sollte mit beiden Systemen vertraut sein und das jeweils geeignetere nutzen je nachdem, was man vor hat.
Wenn man z.B. standardmäßig mit Tabs arbeitet, kann man in einem geöffneten Splitscreen mit Bufferkommandos zwischen den Dateien wechseln.

Vim Plugin – Surround umschließt Text mit Klammern, Anführungszeichen und HTML-Tags

14. Juli 2009 von

Für Vim gibt es ein sehr praktisches Plugin namens Surround, welches es einem ermöglicht Wörter, Sätze, Absätze, Zeilen,… mit Klammern, Anführungszeichen oder XML-Tags zu umschließen. Solche Umschließungen können auch geändert oder gelöscht werden.

Zur Installation wird das Archiv surround.zip im Verzeichnis ~/.vim entpackt.

Grundsätzlich lehnt sich die Bedienung an das Konzept an, den Text zwischen Klammern, Anführungszeichen,… zu ändern so wie es im Artikel Vim Bewegungskommandos im Abschnitt “Spezielle Bewegungskommandos” beschrieben ist.

Text Umschließen
Die Syntax zum Umschließen von Text ist:
ys<BEWEGUNG><ZEICHEN>

Beispiele:

  • ysis" – der aktuelle Satz wird mit doppelten Anführungszeichen umschlossen.
  • ysiw<b> – versieht das aktuelle Wort mit mit dem HTML-Tag b, so dass es fett angezeigt wird.
  • yss) – umschließt die aktuelle Zeile mit runden Klammern.
  • ysi)" – umschließt den Text zwischen den Klammern mit doppelten Anführungszeichen.
  • ysa") – umschließt den den Text zwischen den doppelten Anführungszeichen und die Anführungszeichen selbst mit runden Klammern.

Statt den Bewegungskommandos kann man auch im visuellen Modus den gewünschten Text markieren. Dann drückt man s gefolgt vom gewünschten Zeichen.
Beispiel: s" um den markierten Text mit doppelten Anführungszeichen zu umschließen.

Damit man es sich besser vorstellen kann hier ein konkretes Beispiel. Die folgende Zeile:

Dies ist eine Beispielzeile

wird durch yss" zu

"Dies ist eine Beispielzeile"

Liegt der Cursor auf dem Wort “eine”, so kann man mit ysiw) das Wort mit Klammern umschließen:

"Dies ist (eine) Beispielzeile"

Umschließung ändern
Um die Umschließung von Text zu ändern nutzt man folgende Syntax:
cs<AKTUELLES_ZEICHEN><NEUES_ZEICHEN>

Beispiele:

  • cst" – ändert das XML/HTML-Tag zu doppelten Anführungszeichen.
  • cs"' – ändert doppelte in einfache Anführungszeichen.
  • cs)} – ändert runde in geschweifte Klammern.

Umschließung löschen
Die Syntax um eine Umschließung zu löschen ist:
ds<ZEICHEN>

Beispiele:

  • ds] – löscht eckige Klammern.
  • ds' – löscht einfache Anführungszeichen.
  • dst – löscht XML/HTML-Tags.

Wiederholen
Leider funktioniert das Wiederholen des letzten Kommandos mit Punkt nicht mit dem Surround-Plugin. Jedoch kann man es mit dem Plugin repeat zum funktionieren bringen.
Dafür kopiert man die Datei repeat.vim in das Verzeichnis ~/.vim/autoload/. Nachdem man . (Punkt) gedrückt hat muss man jedoch das Zeichen, welches eingefügt werden soll wiederholen.

Abhilfe schafft ansonsten auch die Nutzung von Makros. Dabei können häufig genutzte Surroundings auch als Makro in die ~/.vimrc gespeichert werden.
Folgende Zeile definiert das Register k so, dass beim Aufruf des Makros k mittels @k das aktuelle Wort in runde Klammern eingeschlossen wird:

let @k="ysiw)"

Whois Plugin für den zBot

10. Juli 2009 von

Vor einiger Zeit habe ich ein Whois-Plugin für meinen Jabber Bot zBot geschrieben. Aus irgendeinem Grund habe ich es nie online gestellt. Dies möchte ich hiermit nachholen. Ich habe den Code noch ein wenig verschönert.

Fauchi95 hat mich gefragt, ob man nicht ein Whois-Plugin schreiben könnte, da ist es mir wieder eingefallen :-)

Die Bedienung ist so wie man es sich denkt. Man sendet dem Bot ein whois gefolgt von der gewünschten Domain und bekommt das Ergebnis zurück gesendet.

Beispiel:

whois zinformatik.de

Zum Installieren des Plugins kopiert man die Datei Whois.pm in das Verzeichnis plugins im Hauptverzeichnis des zBot und startet dann den Bot neu.

Download:
Whois.pm

VNUML – Ein Netzwerksimulator mit User-Mode-Linux

27. Juni 2009 von

Foto: Ben Stanfield

Foto: Ben Stanfield

VNUML (Virtual Network User-Mode-Linux) ist ein Programm um Netzwerke zu simulieren. Dabei werden die beteiligten Rechner nicht nur simuliert, sondern als virtuelle Maschinen gestartet, wodurch sie mit echten Protokollen miteinander kommunizieren. Daher eignet sich dieses Tool sehr gut zum Testen und Lernen z.B von Routingprotokollen. Man kann damit jedoch auch Paketfiltering mittels iptables sowie andere Dienste wie ARP, DNS oder ICMP ausprobieren. Auch eigene Entwicklungen können so getestet werden.
Da für jeden Rechner ein User-Mode-Linux System (englisch) – welches über einen echten Kernel und ein eigenes Dateisystem verfügt – gestartet wird, ist die Simulation sehr realitätsnah und die Rechner verhalten sich wie echte autonome Maschinen.
Für diesen Artikel ist es vorteilhaft, wenn man grundlegende Kenntnisse über Netzwerke besitzt (es wird z.B. vorausgesetzt, dass man weiß was IP-Adressen, Netze und Netzmasken sowie Router sind)

UPDATE: Artikel nochmal überarbeitet

Installation
Für Debian basierte Distributionen gibt es ein .deb Paket, welches zumindest unter Ubuntu problemlos installiert werden kann. Ansonsten kann man sich den Quelltext herunter laden. Eine englische Installationsanleitung ist auch verfügbar.
Ist VNUML installiert, braucht man noch ein Dateisystem. Auf der Projektseite gibt es 2 verschiedene zum downloaden. Ein größeres, welches mehr Programme beinhaltet und ein sehr abgespecktes, welches nützlich ist um größere Netzwerke zu generieren, da für jeden virtuellen Rechner ein Dateisystem im Arbeitsspeicher liegt.
Man kopiert das gewählte Dateisystem nach /usr/share/vnuml/filesystems/filesystem.img. Für die Beispiele in diesem Artikel reicht das kleine, welches man als mini_fs speichern kann. Dafür können die folgenden Befehle benutzt werden, nachdem man die Datei n3vlr-0.11-vnuml-v0.1.tar.gz herunter geladen hat:

tar -xvzf n3vlr-0.11-vnuml-v0.1.tar.gz
sudo cp n3vlr-0.11-vnuml-v0.1.img /usr/share/vnuml/filesystems/mini_fs

Möchte man das Dateisystem ändern um z.B. neue Programme hinzuzufügen oder unbenötigte Dateien zu löschen, kann man dieses mit dem Befehl

sudo mkdir /mnt/vnuml
sudo mount -o loop /usr/share/vnuml/filesystems/filesystem.img /mnt/vnuml

einhängen. Nun kann man im Ordner /mnt/vnunml alle gewünschten Änderungen vornehmen und das Dateisystem danach mit sudo umount /mnt/vnuml wieder aushängen.

Scenariodatei erstellen
Die Netzwerktopologie wird in einer XML-Datei beschrieben. In dieser werden zuerst die globalen Einstellungen festgelegt, in denen unter anderem angegeben wird, wo das zu nutzende Dateisystem liegt und welchen ssh-Key man nutzen möchte um auf die virtuellen Rechner zuzugreifen.
Danach folgen die Definitionen der Netze gefolgt von den Rechnern.
Im folgenden eine minimale Beispielkonfiguration, die zwei Rechner beschreibt, die über ein Netz miteinander verbunden sind. Zuerst der globale Teil, in dem die VNUML-Version, der Name des Scenarios und weitere Einstellungen definiert werden. Dort wird auch das Management-Netz (192.168.0.0/24) definiert, über das man vom eigenen Rechner auf die verschiedenen virtualisierten Maschinen zugreifen kann.
Existiert noch kein öffentlicher ssh-key, so sollte man sich mit folgendem Kommando einen anlegen:

sudo ssh-keygen

Bei der Frage nach einem Passwort drückt man einfach Enter ohne ein Passwort einzugeben. Der vorgeschlagene Pfad sollte stimmen, kann also beibehalten werden.

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE vnuml SYSTEM "/usr/share/xml/vnuml/vnuml.dtd">
 
<vnuml>
    <global>
        <version>1.8</version>
        <simulation_name>beispiel</simulation_name>
        <ssh_version>2</ssh_version>
        <ssh_key>/root/.ssh/id_rsa.pub</ssh_key>
        <automac/>
        <vm_mgmt type="private" network="192.168.0.0" mask="24" offset="100" >
            <host_mapping/>
        </vm_mgmt>
        <vm_defaults exec_mode="mconsole">
            <filesystem type="cow">/usr/share/vnuml/filesystems/mini_fs</filesystem>
            <kernel>/usr/share/vnuml/kernels/linux</kernel>
        </vm_defaults>
    </global>

Als nächstes werden die Netze definiert. In diesem Beispiel gibt es nur ein Netz, da man sich sonst um das Routing kümmern müsste (dazu später mehr).

    <net name="net1" mode="virtual_bridge"/>

Im Modus “virtual_bridge” werden die Interfaces aller virtuellen Rechner sowie alle Netze über Bridges ans Hostsystem (den eigenen Rechner) gekoppelt, so dass man sie mit einem ifconfig sehen und mittels tcpdump oder Wireshark überwachen kann. Dafür wird jedoch das Paket “bridge-utils” benötigt. Alternativ kann man statt dessen auch “uml_switch” benutzen.

Nun folgen die Definitionen der virtuellen Rechner. Bei beiden Rechnern wird ein Interface definiert (es können aber auch mehrere sein, z.B. für Router).

    <vm name="rechner1">
        <if id="1" net="net1">
            <ipv4 mask="255.255.255.0">10.0.1.1</ipv4>
        </if>
    </vm>
 
    <vm name="r2">
        <if id="1" net="net1">
            <ipv4 mask="255.255.255.0">10.0.1.2</ipv4>
        </if>
    </vm>
</vnuml>

Es empfiehlt sich die Datei genauso wie das Scenario (die globale Eigenschaft simulation_name) zu benennen. In diesem Fall also beispiel.xml

Scenario starten und zu den Rechnern verbinden
Um das Scenario zu starten genügt der folgende Aufruf:

sudo vnumlparser.pl -t beispiel.xml

Nachdem das Scenario gestartet ist, kann man sich auf einen der Rechner einloggen:

sudo ssh rechner1

Durch die Angabe des öffentlichen ssh-Keys sollte es keine Passwortabfrage geben. Ansonsten ist das Passwort per default xxxx. Nun kann man alles mögliche Testen. Man kann einen Ping versenden:

ping 10.0.1.2

oder ein Interface überwachen.
Dafür loggt man sich am besten in einer anderen Konsole auf dem 2. Rechner ein:

sudo ssh rechner2

und startet dort einen TCP-Dump:

tcpdump -i eth1

Der Ping sollte die ganze Zeit weiter laufen, damit man auch etwas sehen kann. Danach kann man ihn mit Strg+c stoppen.
Mit exit kann man einen Rechner wieder verlassen.
Da man häufiger auf mehreren Rechnern gleichzeitig eingeloggt sein möchte wenn man mit VNUML arbeitet, bietet es sich an Screen zu benutzen.
Um die Simulation zu beenden führt man folgenden Befehl aus:

sudo vnumlparser.pl -P beispiel.xml

Dienste starten
Wie bereits erwähnt eignet sich VNUML besonders gut zum ausprobieren und Testen von Routingprotokollen. Daher sind auch die Quagga-Implementationen der bekanntesten Routingprotokolle RIP, OSPF und BGP bereits installiert und können recht einfach genutzt werden. Ich werde in diesem Artikel jedoch nur eine Minimalkonfiguration für RIP und OSPF angeben. Eine Einführung in diese Protokolle und deren Konfiguration würde an dieser Stelle zu weit führen.
Um das Routing grundsätzlich zu aktivieren wird das Tag

<forwarding type="ipv4" />

genutzt. Weitere Tags binden ein Konfigurationsverzeichnis conf ein (welches im gleichen Verzeichnis, wie die xml-Datei des Scenarios liegt) und starten die verschiedenen Daemons.
Im Verzeichnis conf sollten dann die folgenden Dateien vorhanden sein:

zebra.conf

!
hostname zebra
!
password xxxx
enable password xxxx

ripd.conf

!
hostname ripd
password xxxx
!
router rip
network 10.0.0.0/8

ospfd.conf

!
hostname ospfd
password xxxx
!
router ospf
network 10.0.0.0/8 area 0

Weitere Infos zu den Quagga-Routingprotokollen gibt es unter http://www.quagga.net.
Ein Scenario, welches der Einfachheit halber nur aus Routern besteht, auf denen man wahlweise OSPF oder RIP starten kann wird im folgenden Beispiel definiert:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE vnuml SYSTEM "/usr/share/xml/vnuml/vnuml.dtd">
 
<vnuml>
    <global>
        <version>1.8</version>
        <simulation_name>mini</simulation_name>
        <ssh_version>2</ssh_version>
        <ssh_key>/root/.ssh/id_rsa.pub</ssh_key>
        <automac/>
        <vm_mgmt type="private" network="192.168.0.0" mask="24" offset="100" >
            <host_mapping/>
        </vm_mgmt>
        <vm_defaults exec_mode="mconsole">
            <filesystem type="cow">/usr/share/vnuml/filesystems/mini_fs</filesystem>
            <kernel>/usr/share/vnuml/kernels/linux</kernel>
        </vm_defaults>
    </global>
 
    <net name="net1" mode="virtual_bridge"/>
    <net name="net2" mode="virtual_bridge"/>
 
    <vm name="r1">
        <if id="1" net="net1">
            <ipv4 mask="255.255.255.0">10.0.1.1</ipv4>
        </if>
 
        <forwarding type="ipv4" />
 
        <filetree root="/etc/quagga" seq="start">conf</filetree>
        <exec seq="start" type="verbatim">sysctl -w net.ipv4.conf.all.rp_filter=0</exec>
        <exec seq="start" type="verbatim">hostname</exec>
        <exec seq="start" type="verbatim">/usr/lib/quagga/zebra -f /etc/quagga/zebra.conf -d</exec>
        <exec seq="rip" type="verbatim">/usr/lib/quagga/ripd -f /etc/quagga/ripd.conf -d</exec>
        <exec seq="ospf" type="verbatim">/usr/lib/quagga/ospfd -f /etc/quagga/ospfd.conf -d -P 2604</exec>
        <exec seq="stop" type="verbatim">hostname</exec>
        <exec seq="stop" type="verbatim">killall zebra</exec>
        <exec seq="stop" type="verbatim">killall ripd</exec>
        <exec seq="stop" type="verbatim">killall ospfd</exec>
 
        <exec seq="rpfilter" type= "verbatim">
            for f in /proc/sys/net/ipv4/conf/*/rp_filter; do echo 0 > $f; done
        </exec>
    </vm>
 
    <vm name="r2">
        <if id="1" net="net1">
            <ipv4 mask="255.255.255.0">10.0.1.2</ipv4>
        </if>
        <if id="2" net="net2">
            <ipv4 mask="255.255.255.0">10.0.2.1</ipv4>
        </if>
 
        <forwarding type="ipv4" />
 
        <filetree root="/etc/quagga" seq="start">conf</filetree>
        <exec seq="start" type="verbatim">sysctl -w net.ipv4.conf.all.rp_filter=0</exec>
        <exec seq="start" type="verbatim">hostname</exec>
        <exec seq="start" type="verbatim">/usr/lib/quagga/zebra -f /etc/quagga/zebra.conf -d</exec>
        <exec seq="rip" type="verbatim">/usr/lib/quagga/ripd -f /etc/quagga/ripd.conf -d</exec>
        <exec seq="ospf" type="verbatim">/usr/lib/quagga/ospfd -f /etc/quagga/ospfd.conf -d -P 2604</exec>
        <exec seq="stop" type="verbatim">hostname</exec>
        <exec seq="stop" type="verbatim">killall zebra</exec>
        <exec seq="stop" type="verbatim">killall ripd</exec>
        <exec seq="stop" type="verbatim">killall ospfd</exec>
 
        <exec seq="rpfilter" type= "verbatim">
            for f in /proc/sys/net/ipv4/conf/*/rp_filter; do echo 0 > $f; done
        </exec>
    </vm>
 
    <vm name="r3">
        <if id="1" net="net2">
            <ipv4 mask="255.255.255.0">10.0.2.2</ipv4>
        </if>
 
        <forwarding type="ipv4" />
 
        <filetree root="/etc/quagga" seq="start">conf</filetree>
        <exec seq="start" type="verbatim">sysctl -w net.ipv4.conf.all.rp_filter=0</exec>
        <exec seq="start" type="verbatim">hostname</exec>
        <exec seq="start" type="verbatim">/usr/lib/quagga/zebra -f /etc/quagga/zebra.conf -d</exec>
        <exec seq="rip" type="verbatim">/usr/lib/quagga/ripd -f /etc/quagga/ripd.conf -d</exec>
        <exec seq="ospf" type="verbatim">/usr/lib/quagga/ospfd -f /etc/quagga/ospfd.conf -d -P 2604</exec>
        <exec seq="stop" type="verbatim">hostname</exec>
        <exec seq="stop" type="verbatim">killall zebra</exec>
        <exec seq="stop" type="verbatim">killall ripd</exec>
        <exec seq="stop" type="verbatim">killall ospfd</exec>
 
        <exec seq="rpfilter" type= "verbatim">
            for f in /proc/sys/net/ipv4/conf/*/rp_filter; do echo 0 > $f; done
        </exec>
    </vm>
</vnuml>

Die Topologie des Beispielscenarios mini.xml

Die Topologie des Beispielscenarios mini.xml

Dieses Beispiel besteht aus 3 Routern, die mit zwei Netzen zu einer “Kette” verbunden sind (siehe Abbildung rechts). Startet man dieses Scenario, so kann man nicht von r1 (10.0.1.1) nach r3 (10.0.2.2) pingen, da die Routingdaemons noch nicht gestartet sind und r1 noch nichts von net2 weiß:

sudo vnumlparser.pl -t mini.xml
sudo ssh root@r1
ping 10.0.2.2

Wie man sieht, kommen die Pings nicht bei r3 an. Mit exit verläst man den Router r1 wieder.
Es gibt nun 4 Sequenzen, die ausgeführt werden können: start, stop, rip und ospf. Dabei wird durch ausführen der Sequenz start der Hostname gesetzt und der zebra-Daemon gestartet. Mit rip oder ospf wird der entsprechende Routingdaemon gestartet und stop beendet alle Routingprozesse.
Man startet nun also z.B. den RIP-Daemon mit den folgenden Befehlen:

sudo vnumlparser.pl -x start@mini.xml
sudo vnumlparser.pl -x rip@mini.xml

Nun kann man testen, ob das Routing auch funktioniert, indem man den Ping, der vorher fehlschlug wiederholt:

sudo ssh root@r1
ping 10.0.2.2

Jetzt sollte der Ping funktionierten. Bei größeren Scenarien kann es einige Sekunden dauern bis alle Router über die notwendigen Informationen verfügen (also bis das Scenario konvergent ist).

Natürlich gibt es noch viele weitere Optionen und Möglichkeiten, die VNUML zur Verfügung stellt. Dies soll nur eine kleine Einführung sein, um die ersten Schritte mit diesem System zu machen.

Links

Vim Plugin – Tasklist sammelt Infos über offene und fertige Todos

23. Juni 2009 von

Das Vim Plugin Tasklist ist ein kleines aber praktisches Plugin, welches im aktuellen Text nach den Wörtern TODO, XXX, FIXME und DONE sucht und eine Liste daraus erstellt.

Sobald das Plugin installiert ist (indem die Datei tasklist.vim nach ~/.vim/plugin/ kopiert wurde), kann man die TODO-Liste mit \t generieren und angezeigen.

Dabei öffnet sich ein horizontaler Splitscreen, in dem alle Vorkommen von TODO, XXX und FIXME sortiert nach Vorkommen und mit Angabe der Zeilennummer aufgeführt werden. Dabei wird auch der Rest der Zeile hinter dem Schlüsselwort angezeigt, so dass man auch sehen kann worum es bei einem TODO geht.

Wenn man mit j und k durch die Liste navigiert wird die entsprechende Textstelle im eigentlichen Text jeweils automatisch angesprungen. Drückt man Enter, so schließt sich der Splitscreen und man befindet sich an der Stelle des zuletzt ausgewählten TODOs im Text.

Die mit DONE gekennzeichneten Textstellen werden unter den noch offenen TODOs angezeigt. Ansonsten funktionieren sie genauso wie TODOs.

Nach jedem Speichervorgang kann die Liste mit \t neu generiert werden.

POV-Ray – ein Raytracer

21. Juni 2009 von
Ein mit POV-Ray generiertes Bild

Ein mit POV-Ray generiertes Bild

Mit dem quelloffnen Raytracer POV-Ray kann man sehr realitätsnahe Bilder erzeugen. Anders als bei den meisten anderen 3D-Grafikprogrammen arbeitet man hier nicht mit einer graphischen Oberfläche und Maus sondern beschreibt die Objekte textbasiert über dessen Positionen in einem Koordinatensystem.

[UPDATE]Artikel nochmals überarbeitet und Beispiel hinzugefügt.[/UPDATE]

Was ist Raytracing?
Raytracing ist eine Methode um Computergenerierte Bilder zu erzeugen. Der Unterschied zum Rendering besteht darin, dass keine Gittermodelle mit Texturen belegt werden und die Farbe dann mittels des Lichtes berechnet wird sondern eine Strahlenverfolgung statt findet, wodurch viel realistischere Bilder entstehen. Leider ist dieses Verfahren auch wesentlich rechenintensiver. Dafür bekommt man Schatten und Spiegelungen quasi geschenkt, was mit Rendering relativ schwer zu realisieren ist. (Siehe auch: http://de.wikipedia.org/wiki/Raytracing)

Einen guten Eindruck, was POV-Ray leisten kann bekommt man in der Galerie der POV-Ray Homepage.

Download und Installation
POV-Ray steht unter einer eigenen Lizenz, die zwar das Einsehen des Quelltextes, aber nicht die veränderte Weitergabe im Sinne freier Software erlaubt (was sich aber bald ändern soll, siehe Kommentare).

Das Programm ist für alle gängigen Betriebssysteme verfügbar und kann sogar in einem Cluster (also auf mehreren PC’s gleichzeitig) verwendet werden.
[UPDATE]POV-Ray kann unter Ubuntu mittels sudo apt-get install povray installiert werden.
Ansonsten kann man die Binärdateien von der Homepage beziehen[/UPDATE]

Grundsätzliche Funktionsweise
In einer Scenenbeschreibungssprache werden alle Objekte, Lichtquellen und die Kamera an 3D-Positionen im Raum definiert (z.B. Kugel an Stelle x,y,z mit Radius r und Farbe rot). Daneben gibt es noch viele weitere Optionen um bestimmte Materialien zu simulieren. Daraus wird dann das Bild berechnet.

Zitat:

Der Qualität und dem Anspruch der gerenderten Bilder sind keine theoretischen Grenzen gesetzt;
in der Praxis ist die zur Verfügung stehende Rechen- oder Computer-Zeit der begrenzende Faktor.

Quelle: http://de.wikipedia.org/wiki/Povray

Interessant ist Povray durch seine Scenenbeschreibungssprache auch wegen der Automatisierbarkeit.
z.B. ist EAGLE ein Programm um elektronische Schaltungen zu entwerfen und daraus entsprechende Boardlayouts zu konstruieren. Mittels eines Scripts kann man sich die Platine zu einem fertigen Layout vor dem eigentlichen Bau mit POV-Ray Rendern lassen um sich ansehen zu können, wie es später aussehen wird. (Macht sich sehr gut in Ausarbeitungen oder um vorab etwas präsentieren zu können.)

Das Board-Layout eines USB<->UART Konverters

Das Board-Layout eines USB<->UART Konverters

Das mit POV-Ray aus dem Board-Layout generierte Bild

Das mit POV-Ray aus dem Board-Layout generierte Bild

Ein Foto der fertigen Platine

Ein Foto der fertigen Platine (um 180° gedreht)

Übrigens ist der linke Teil meines Banners (oben auf der Seite) auch ein Teil einer mit POV-Ray gerenderten Platine. Der Rechte Teil ist ein Ausschnitt des EALGE Layouts, aus dem es generiert wurde.

Beispiel
Im folgenden Beispiel wird eine einfache Scene erstellt. Zuerst wird eine Datei mit Farbdefinitionen eingebunden, damit man nicht jede Farbe als RGB-Wert eingeben braucht. Danach wird eine Kamera definiert. Dabei gibt man die Position an, wo sie sich befinden soll und die Position, auf die die Kamera zeigen soll.
Als nächstes muss noch eine Lichtquelle definiert werden, damit man auch etwas sehen kann. Diese wird mit dem Schlüsselwort light_source eingeleitet und hat eine Position und eine Farbe. Nun können die einzelnen Objekte definiert werden.
Als Boden wird eine Ebene definiert, die schwarz-weiß kariert ist und waagerecht auf der Höhe -1 liegt. Die Koordinaten geben die Lage der Ebene an, die immer Senkrecht auf dem angegebenen Vektor liegt. Dahinter kann man ein Offset (der Abstand zum Nullpunkt), in diesem Fall also die Höhe angeben.
Die Farbe wird mit dem Schlüsselwort “pigment” angegeben. Da die Ebene Kariert sein soll nutzen wir hier die Option “checker” gefolgt von zwei Farbwerten.
Durch die Include-Anweisung am Anfang können hier die Namen der Farben verwendet werden. Ansonsten müsste man den RGB-Wert angeben.
Der Himmel wird durch ein “sky_sphere”-Objekt erzeugt, welches entlang der y-Achse (“gradient y”) von Hellblau nach Blau verläuft (“color_map”).
Nun kann man noch weitere Objekte auf der Ebene platzieren. Eine Kugel (sphere) besitzt einen Mittelpunkt und eine Durchmesser und natürlich auch eine Farbe.
Ein Kegel (cone) hat zwei Koordinaten, die den Mittelpunkte der beiden Enden entsprechen sowie je einen Durchmesser an jedem Ende.

Neben der Farbe kann auch noch die Oberflächenstruktur und -Politur definiert werden. Für die Struktur ist das Schlüsselwort “normal” zuständig, die Politur wird mittels “finish” angegeben. Im Beispiel wird der 2. Kugel eine reflektierende Politur gegeben, so dass sie die anderen Objekte spiegelt. (je höher der Reflektionswert, desto stärker die Spiegelung.

Nun der Code des Beispiels:

#include "colors.inc"
 
camera {    // Die Kamera
    location <2, 3, -6>
    look_at <0, 1, 2>
}
 
light_source { // Die Lichtquelle
    <3, 5, -4>
    color White
}
 
plane { // Eine Ebene
    <0, 1, 0>, -1
    pigment { checker color White, color Black }
} 
 
sky_sphere { // Der Himmel
    pigment {
        gradient y
        color_map { [0.0 color rgb <0.7,0.7,1.0>] [1.0 color blue 0.5] }
    }
}
 
sphere { // eine Kugel
    <-3, 1, 4>, 2
    pigment { color Yellow }
}  
 
cone{   // Ein Kegel
    <3,-1,3>,1,<2.5,4,4>,0
    pigment{color Green}
}
 
sphere { // Eine reflektierende Kugel
    <0, 2.5, 10>, 3
    finish{
        reflection {
            0.8       
        }
    }
}
Das Ergebnis des Beispiels

Das Ergebnis des Beispiels

Sonstige Funktionen
POV-Ray kennt noch eine ganze Menge weiterer Objekte, die sich auch zusammenfassen lassen. Man kann auch – wie in der Mengenlehre – ein Objekt von einem anderen abziehen oder die Schnittmenge zweier Objekte berechnen (und anzeigen).
Auch bei den Farben und Oberflächenstrukturen bzw. -Polituren gibt es noch viele weitere Möglichkeiten und Optionen.

Die Objekte können skaliert (in der Größe geändert) rotiert und translatiert (verschoben) werden.
Es können auch Kontrollstrukturen wie bei Programmiersprachen genutzt werden. So kann man Variablen deklarieren, Schleifen und Verzweigungen nutzen sowie Funktionen (bei POV-Ray Makros genannt) definieren um automatisch eine Reihe von Objekten zu erzeugen und zu transformieren.

Man kann mit POV-Ray auch Animationen erstellen. Dafür werden per Script mehrere Bilder erstellt, wobei vor jedem Bild eine Variable verändert wird. Diese kann genutzt werden um die Kamera oder Objekte zu bewegen.
Hier einige Beispiele (auf Youtube gibt es noch jede Menge weitere)

YouTube Preview Image YouTube Preview Image

Links

Vim als Hexeditor – Binärdateien bearbeiten

13. Juni 2009 von

Vim lässt sich selbstverständlich auch als Hexeditor nutzen. Dafür wird (normalerweise) gleichzeitig mit Vim das kleine Programm xxd installiert. Dieses sollte also auf jedem System zu finden sein, auf dem Vim installiert ist.

Wenn man Binärdateien öffnet, sollte man die Option -b von Vim nutzen, was den Binärmodus anschaltet:

vim -b datei.bin

xxd kann nun mittels eines Filters auf die geöffnete Datei angewendet werden:

:%!xxd

Damit wird aus dem folgenden Inhalt

Ein Test

die Hex-Repräsentation

00000000: 4569 6e20 5465 7374 0a                   Ein Test.

Die Zahl vor dem Doppelpunkt ist das Offset des ersten Zeichens in der Zeile (in hexadezimaler Schreibweise), also das wievielte Zeichen es ist. Danach folgt die hexadezimale Repräsentation der Zeile bestehend aus (bis zu) 16 Bytes. Danach sieht man die ASCII-Repräsentation der Zeile.
Nun kann man die hexadezimale Repräsentation beliebig ändern, wobei jedoch die ASCII-Repräsentation so bleibt, wie sie war. Sie wird nicht automatisch geändert.

Wenn man mit der Bearbeitung fertig ist, kann man xxd mit der Option -r aufrufen um wieder zur normalen Ansicht zurück zu kehren:

:%!xxd -r

Für die xxd Kommandos kann man sich nun Mappings erstellen. Dafür fügt man die beiden folgenden Zeilen in die ~/.vimrc ein:

map <leader>hex :%!xxd<CR>
map <leader>nhex :%!xxd -r<CR>

Nun kann man mittels \hex in den “Hexmodus” wechseln und mit \nhex wieder zurück. (Den Leader kann man z.B. mit der Zeile let mapleader="," auf , setzen, so dass man die Befehle mit ,hex und ,nhex aufrufen kann)

Das Plugin hexman
Das Bearbeiten von Dateien in der hexadezimalen Repräsentation wird durch das Plugin hexman erleichtert. Nachdem man die Datei hexman.vim ins Pluginverzeichnis (~/.vim/plugin) kopiert hat, kann man einfach folgende Befehle nutzen (Leader wird hier als \ angenommen):

  • \hm – wechselt zwischen Hexmodus und normalem Modus
  • TAB – bewegt den Cursor zum Anfang des nächsten ASCII Zeichens (da ein Zeichen ja aus 2 Hex-Ziffern besteht)
  • \hd – löscht das Zeichen unter dem Cursor
  • \hi – fügt ein ASCII-Zeichen vor dem Cursor ein
  • \hg – Springt zu einem Offset

In der Statuszeile wird jeweils das aktuelle Offset (des Cursors) in dezimaler und hexadezimaler Schreibweise angezeigt. In der ASCII-Repräsentation wird die Spalte hervorgehoben, in der sich der Cursor in der Hex-Repräsentation befindet. Wenn man die Befehle des Plugins zum Ändern von Werten benutzt, wird die ASCII-Repräsentation automatisch aktualisiert, so dass sie immer mit den Hexadezimalwerten überein stimmt.

Auch hier ist ein Mapping vorteilhaft, welches einem das Ändern eines Zeichens mittels \hc erlaubt:

map <leader>hc <leader>hd <leader>hi

NaturalDocs – Quelltexte natürlich dokumentieren

7. Juni 2009 von
NaturalDocs Dokuementation des zBot

NaturalDocs Dokuementation des zBot

Da mir POD/PerlDoc nicht gefällt, habe ich mich vor einiger Zeit auf die Suche nach einer Alternative gemacht und bin auf NaturalDocs gestoßen. Mit diesem System können eine ganze Reihe von Programmiersprachen dokumentiert werden, wie z.B. perl, C#, c++, Makefiles, Ruby, Python, PHP, ActionScript, Java, JavaScript, Pascal, ADA, TCL, …

Sehr schön an NaturalDocs ist, dass die Dokumentation sehr nahe an natürlichsprachlichem Plaintext ist und sich die Beschreibungen von Klassen oder Methoden auch sehr gut aus den Quellen lesen lässt ohne dass man die Syntax von NaturalDocs kennen muss. Auch einfache Textdateien wie eine Readme oder ähnliches können damit erstellt werden. So kann man (zumindest bei kleineren Projekten) sogar sämtliche Dokumente wie Anforderungen, UML-Diagramme, … mit NaturalDocs erstellen, wodurch man alle Informationen an einem Ort gebündelt und in einem einheitlichen Format vorliegen hat.

Das Perl-Tool versteht auch JavaDoc, so dass eine Umstellung erleichtert wird.

Gestartet wird NaturalDocs mittels:
NaturalDocs -i [input (source) directory]
-o [output format] [output directory]
-p [project directory]
[options]

wobei ich mir ein kleines Script zum erstellen/aktualisieren der Dokumentation erstellt habe, welches ein Changelog beinhaltet, welches aus einem svn log automatisch generiert wird. Das Script habe ich unten angehängt.

Ein Beispiel in perl:

# SUB: multiplicate
# 
# multiplicates two numbers
# 
# PARAMETERS:
# $a - first parameter
# $b - second parameter
#
# RETURNS:
# the product of $a and $b
sub multiplicate {
    $a=shift;
    $b=shift;
    return $a*$b;
}

So sieht die Dokumentation einer einfachen Funktion aus. Bei Sprachen die full language support besitzen (bisher perl, ActionScript und C#) kann auch eine JavDoc-artige Dokumentation genutzt werden:

##
# multiplicates two numbers
# 
# PARAMETERS:
# $a - first parameter
# $b - second parameter
#
# RETURNS:
# the product of $a and $bsub multiplicate {
    $a=shift;
    $b=shift;
    return $a*$b;
}

Beide Beispiele haben das selbe Ergebnis:

NaturalDocs Beispiel

NaturalDocs Beispiel

Listen können erstellt werden, indem eine Zeile mit “-” angefangen wird. Definitionen haben ein “-” zwischen Bezeichner und Definition. Es können auch Grafiken, Beispielquelltexte und ASCII-Diagramme eingefügt werden.

Leider kann NaturalDocs von Haus aus nicht mit Listen in Listen umgehen, doch dafür gibt es einen Patch: Nested Bullets, womit man durch + oder * eine Liste in der Liste einleitet.
Installiert wird es, indem die Datei Native.pm.diff nach $NATURALDOCS_PATH/Modules/NaturalDocs/Parser Kopiert wird und dann der Befehl

patch Native.pm Native.pm.diff

aufgerufen wird.

Einen neuen Absatz erzwingt man durch eine Leerzeile. Eine Überschrift kann mittels # Überschrift: eingefügt werden, wobei die Zeile darüber leer sein muss.
Es kann auch auf Webseiten, Emailadressen und andere Stellen der Dokumentation verlinkt werden.
Natürlich kann auch unterstrichen und fett geschrieben werden. Die Zusammenfassung wird automatisch erstellt.

Cool ist auch die Möglichkeit der Abkürzung, womit man mehrere Defines, Funktionen oder Variablen zusammenfassend dokumentieren kann. So kann man statt dem folgenden Code

# VARIABLE: $configFile
# Filename of configuration file
$configFile = "config.txt";
 
# VARIABLE: $inputFile
# Filename of input file
$inputFile = "input.txt";
 
# VARIABLE: $outputFile
# Filename of output file
$outputFile = "out.txt";

die Variablen für die Dateinamen zusammen fassen:

# VARIABLES: Filenames
# $configFile - Filename of configuration file
# $inputFile - Filename of input file
# $outputFile - Filename of output file
$configFile = "config.txt";
$inputFile = "input.txt";
$outputFile = "out.txt";

Dabei können mehrere solcher Blöcke für verschiedene Belange angelegt werden (z.B. Dateinamen, Logindaten für Datenbank, …). Das Ergebnis sieht dann so aus:

NaturalDocs - Variablen zusammenfassend dokumentiert

NaturalDocs - Variablen zusammenfassend dokumentiert

Auch mein Jabber Bot zBot ist mit NaturalDocs dokumentiert. Als Beispiel kann man sich dessen Dokumentation ansehen.

Für Neulinge gibt es ein schönes Walktrough, wo die ersten Schritte mit NaturalDocs erklärt werden.

Hier noch das Script, welches eine von NaturalDocs lesbare Changelist im Ordner documents und dann die Dokumentation selbst erstellt:

#!/usr/bin/perl
 
# Script: makedocs.pl
#
# This script generates the documentation.
#
# Requirements:
#
# - NaturalDocs path must be in ENV variable $NATURALDOCS_PATH
# - Projectdirectory naturaldocs has to be in the same directory as this script
# - There must be a (empty) directory documentation in the same directory as this script
#
# Usage:
#
# Just start this script when something has changed or use the script <make.pl>
#
# > tools/makedocs.pl [OPTIONS]
#
# Options:
#
#  -o - start makedocs.pl in offline modus
#
# In offlinemode the changelog is not generated
#
#
# SVN:
#
# Commit only the textfiles of the projectdirectory (Not the directory "Data") from NaturalDocs.
#
# The documentation directory should be an empty dir in SVN.
#
# So everybody can create the documentation by himself just by executing this script.
 
use strict;
use warnings;
use vars qw (%ENV);
 
# Sub: generatechangelog
#
# Generates documents/changelog.txt from svn log -v
#
sub generatechangelog {
    print "Generating changelog...n";
    $ENV{LANG} = "C";
    my $log = `svn log -v`; 
 
    $log =~ s/(-){2,}//g;
    $log =~ s/(r[0-9]{1,4})/$1:nn$1/g;
    $log =~ s/n/nn/g;
    $log =~ s/Pfade:/Pfade/g;
    $log =~ s/paths:/paths/g;
    $log =~ s/([A-Z] /)/- $1/g;
 
    open(DATEI, ">documents/changelog.txt");
    print DATEI "Title: Changelognn$log";
    close DATEI;
    print "Done.n";
}
 
######### PROGRAM START ############
 
if (defined $ENV{NATURALDOCS_PATH} && $ENV{NATURALDOCS_PATH} ne "") {
    generatechangelog() if (not(defined @ARGV && $ARGV[0] eq "-o"));
# Generate documentation of current directory in HTML and save to directory documentation. Projectdirectory is naturaldocs.
# Ignore directory tests
    system
"$ENV{NATURALDOCS_PATH}/NaturalDocs -i . -o HTML ./documentation -p ./naturaldocs -xi ./tests";
} else {
    print "Environment variable $NATURALDOCS_PATH not defined!n";
}

Perl Einzeiler auf der Konsole

3. Juni 2009 von

Ähnlich wie bei awk kann man perl das Programm auf der Konsole direkt übergeben. Dazu ruft man perl mit der Option -e auf. Das Programm muss dann in Hochkommata eingeschlossen werden.
Beispiel:

perl -e 'print "Hello World!\n"'

Um jede print-Anweisung mit einem “newline” abzuschließen, kann man zusätzlich die Option -l benutzen:

perl -l -e 'print "Hello World!"; print "Hello Ubuntuusers!"'

Um eine Datei Zeile für Zeile durchzugehen, gibt es die Option -n. Das Program beschreibt dann ähnlich wie bei awk was mit jeder Zeile geschehen soll:

perl -n -l -e 'print $_ if $_ =~ /foo/"' datei.txt

gibt alle Zeilen aus, die “foo” enthalten.
Die Option -n entspricht folgendem Code:

while(<>){
    # Der Code, der übergeben wird
}

Die Option -a bringt perl noch einen Schritt näher zu awk. Damit werden die Wörter einer Zeile (die durch Leerzeichen getrennt sind) in das Array @F geladen. Den Worttrenner kann man mit der Option -F setzen:

perl -n -a -F; -e 'print $F[$#F]' datei.csv

gibt von jeder Zeile das letzte Element einer csv (Comma Separated Value) Datei aus.
Dies entspricht folgendem Code:

while(<>){
    @F = split($pattern);
    # Der übergebene Code
}

wobei $pattern das mit -F übergebene Pattern (im obigen Beispiel ";") ist. Dadurch sind auch reguläre Ausdrücke wie -F/[0-9]+/ möglich.

Es können auch die Schlüsselwörter BEGIN und END gesetzt werden um einen Block vor oder nach der Hauptschleife auszuführen:

perl -n -l -a -e 'BEGIN{$x=0} {$x+=$F[$#F]} END{print $x}' preisliste.txt

errechnet den Gesammtpreis einer Preisliste, in der am Ende jeder Zeile der Preis steht. Es wird also von jeder Zeile das letzte Wort addiert. Man könnte das Programm jetzt auch noch etwas kürzer schreiben:

perl -nlae '$x+=$F[$#F]; END{print $x}' preisliste.txt

Dies entspricht dem awk-Programm:

awk '{x+=$NF} END{print x}' preisliste.txt

Für das Suchen und Ersetzen mit Regulären Ausdrücken eignet sich die Option -p. Diese Funktioniert genau wie -n mit dem Unterschied, dass jede Zeile automatisch ausgegeben wird. So kann man wie mit sed Dateien ändern:

perl -pe 's/foo/bar/g' datei.txt > datei_new.txt

ersetzt jedes Vorkommen von “foo” durch “bar” und schreibt das Ergebnis in die Datei “datei_new.txt”.

Um die Datei direkt zu ändern, kann man die Option -i verwenden. Dieser kann optional ein String mitgegeben, der an den verwendeten Dateinamen angehängt den Dateinamen einer anzulegenden Sicherheitskopie ergibt:

perl -pi -e 's/foo/bar/g' *.txt
perl -pi.orig -e 's/foo/bar/g' datei.txt

Beim ersten Befehl jede Text-Datei im aktuellen Verzeichnis direkt geändert. Beim zweiten wird die “datei.txt” nach “datei.txt.orig” kopiert bevor jedes Vorkommen von “foo” durch “bar” ersetzt wird. (Man kann natürlich auch mit dem 2. Befehl beliebig viele Dateien bearbeiten, wenn man * benutzt.)

Module
Die Option -M erlaubt es einem beliebige Module einzubinden, die dann im Programm benutzt werden können. So kann man z.B. mit dem folgenden Befehl mit dem Modul LWP::Simple eine Webite laden und den HTML-Code ausgeben:

ls | perl -MLWP::Simple -e 'getprint("http://zinformatik.de")'

Mit dem folgenden Befehl werden von allen iso Dateien im Verzeichnis MD5-Summen erstellt:

ls *.iso | perl -MDigest::MD5 -nle 'open(FILE,$_); $d=Digest::MD5->new; $d->addfile(FILE); print $d->hexdigest'

Fazit
Für kleinere kosmetische Änderungen eines Textes oder einer Ausgabe sowie zum extrahieren von Informationen daraus ist awk meist besser geeignet. Bei komplexeren Aufgabenstellungen ist die Mächtigkeit von perl jedoch vorteilhafter.
Vor allem durch die Möglichkeit der Dateioperationen sollen manche Aktionen beschleunigt werden können:
Statt des Aufrufs:

find -name "*.bak" -exec rm "{}" \;

der für jede gefundene Datei einen neuen Prozess startet um sie zu löschen kann man folgenden Befehl nutzen:

find -name "*.bak" -print | perl -nle 'unlink'

Es ist jedenfalls nicht verkehrt beides zu kennen, ganz nach dem Motto: Für jeden Zweck die richtige Programmiersprache.

[UPDATE]Mehr informationen liefert der Befehl perldoc perlrun (perldoc muss installiert sein) oder die Seite http://p3rl.org/perlrun[/UPDATE]


Bloggeramt.de frisch gebloggt Blogverzeichnis - Blog Verzeichnis bloggerei.de