Genau wie ein Handwerker penibel auf den Inhalt seines Werkzeugkoffers achtet, pflegt jeder Programmierer seine persönliche Sammlung unentbehrlicher Skripts. Da Perl-Werkzeuge öfter mal CPAN-Module benötigen, die auf einer reparaturbedürftigen Maschine nicht unbedingt vorliegen, bringt der heute vorgestellte Werkzeugkasten einfach alles mit.
Perl ist ja bekannt dafür, dass man mit nur ganz wenigen Zeilen sehr viel Arbeit erledigen kann. Heute soll's mal um vier Skripts gehen, die zwar trivial implementiert, aber extrem nützlich sind. So nützlich, dass man sie eigentlich überall dabeihaben sollte.
Leider arbeiten Entwickler aber auch oft auf Maschinen, die nicht
die neueste Perl-Distribution fahren oder das ein oder andere CPAN-Modul
nicht installiert
haben. Zwar lässt sich das alles schnell über's Web und
mit einer CPAN-Shell beheben, aber es wäre schön, die gesamte
Werkzeugkiste sofort betriebsbereit zu haben, wenn nur ein rudimentäres
perl
installiert ist.
Zum Glück hat Autrijus Tang mit dem CPAN-Modul PAR
eine Möglichkeit
gefunden, Applikationen mit allen erforderlichen Modulen in Archive
zu verpacken, ähnlich wie das unter Java mit .jar
-Dateien funktioniert.
Da das Perl Archive Toolkit PAR
aber nicht unbedingt auf der Zielmaschine
verfügbar ist, um ein Archiv zu entpacken, kann man mit PAR
sogar alles
enthaltende Executables zusammenbauen, die
dann magisch auf der Zielmaschine Perlskripts ablaufen lassen, für die
die richtige Umgebung eigentlich fehlt.
Auf geht's, beim Schichtl! Hier sind vier meiner geschätzten Werkzeuge, die später ordnungsgemäß verschnürt werden.
Ein kleiner Base64-(De)Kodierer zum Beispiel ist immer nützlich, wenn man
auf dem Web mit Basic Auth arbeitet. Neulich hatte ich mal das Passwort
einer Webseite vergessen, die den Browser diese typische Dialogbox
in Abbildung 1
aufpoppen ließ. Der Browser erinnerte sich an meine früheren Eingaben
und füllte die Felder aus, allerdings bestand das Passwortfeld nur
aus Sternchen. Aber ein flugs zwischen Browser und Server geschalteter
Proxy (z.B. [1]) bringt in Abbildung 2
zum Vorschein, dass ein String wie dGVzdDpzZWNyZXQ=
durch die
Leitung fliegt.
Abbildung 1: Der Browser fragt im Basic-Auth-Dialog nach Username und Passwort. |
Abbildung 2: Der Base64-String taucht im Log des Proxies auf. |
Was steht dort im Klartext? Das Skript in Listing b64.pl
bringt es an den Tag:
$ b64.pl -d dGVzdDpzZWNyZXQ= test:secret
Aha, der Username ist test
, das Passwort ist secret
. Das überrascht
nicht, denn es ist ja bekannt, dass Basic Auth wenig nützt,
wenn jemand in der Leitung schnüffelt. Umgekehrt zeigt
$ b64.pl test:secret dGVzdDpzZWNyZXQ=
dass b64.pl
auch die Kodierung beherrscht. Andere Anwendungen gibt
es viele: Base64-Kodierung kommt immer dann zum Einsatz, wenn es
darum geht, binäre Daten in ein anzeigbares Format umzuwandeln.
01 #!/usr/bin/perl 02 use warnings; 03 use strict; 04 05 use Getopt::Std; 06 use MIME::Base64; 07 08 getopts "d", \my %opts; 09 10 die "usage: $0 [-d] string" unless 11 defined $ARGV[0]; 12 13 if($opts{d}) { 14 print decode_base64($ARGV[0]), "\n"; 15 } else { 16 print encode_base64($ARGV[0]); 17 }
Auch in URLs sieht man manchmal codierte Sequenzen. Wenn der Browser per GET-Request einen Parameter an den Server schickt, sieht das unter Umständen so aus:
http://host.com/cgi/foo?p=a%20b%2Fc
Jedes Sonderzeichen wurde vom Browser ins
Format %xx umgewandelt, wobei xx der Hexadezimalwert der ASCII-Nummer
des Zeichens ist.
Mit dem simplen Skript in Listing urlcode.pl
lässt sich die
Hex-Codierung leicht dekodieren:
$ urlcode.pl -d a%20b%2Fc a b/c
Umgekehrt lässt sich auch eine Zeichenkette zu Testzwecken URL-kodieren.
Der Aufruf von urlcode
ohne -d
wandelt einen übergebenen String ins URL-Format um:
$ urlcode.pl "a b/c" a%20b%2Fc
Dank des CPAN-Moduls URI::Escape
ist das Skript urlcode.pl
trivial, es testet
lediglich mit Getopt::Std
, ob -d
auf der Kommandozeile vorliegt
und ruft dann entsprechend uri_escape
oder uri_unescape
aus
URI::Escape
auf.
01 #!/usr/bin/perl 02 use warnings; 03 use strict; 04 05 use Getopt::Std; 06 use URI::Escape; 07 08 getopts "d", \my %opts; 09 10 die "usage: $0 [-d] string" unless 11 defined $ARGV[0]; 12 13 if($opts{d}) { 14 print uri_unescape($ARGV[0]), "\n"; 15 } else { 16 print uri_escape($ARGV[0]), "\n"; 17 }
Binäre Dateien pflastern den Bildschirm mit Sonderzeichen voll und hängen
manchmal sogar das benutzte Terminal auf, wenn man sie mit cat
anzeigt.
less
ist besser, hilft aber auch nicht viel weiter, da es nicht genau
angibt, wie lang bestimmte Byte-Sequenzen sind.
Das CPAN-Modul Data::Hexdumper
hingegen bietet eine Anzeige, wie ich
sie schon vor 15 Jahren auf meinem Atari ST1040 schätzte: Links die
Hexcodes in Gruppen von 16 Bytes und rechts die Übersetzung in lesbare
Zeichen, falls dies möglich ist. Abbildung 3 zeigt, wie hd.pl
seinen
eigenen Quellcode als Hexdump anzeigt.
01 #!/usr/bin/perl 02 use warnings; 03 use strict; 04 05 my $data = join '', <>; 06 use Data::Hexdumper; 07 my $results = hexdump( 08 data => $data, 09 number_format => 'C', 10 ); 11 print $results;
Listing hd.pl
ist nur eine schon peinlich triviale Adaption der
Data::Hexdumper
-Manualseite -- aber selbst ein so einfaches Werkzeug
spart oft enorm Zeit!
Abbildung 3: hd.pl zeigt seinen eigenen Quellcode als Hexdump an. |
Wer viel mit Perl arbeitet, stets mit zitternden Fingern die neueste Distribution ausprobiert oder nur schnell mal feststellen will, ob ein Modul auch mit Antik-Versionen wie 5.00503 funktioniert, braucht die Möglichkeit, schnell zwischen verschiedenen Installationen hin- und herzuspringen.
Dazu installiert man Perl-Distributionen nicht mehr einfach unter /usr
,
sondern zum Beispiel in einem Verzeichnis perl-installs
im
Home-Verzeichnis. perl 5.8.4
konfiguriert man zum Beispiel folgendermaßen:
./Configure -D prefix=$HOME/perl-installs/perl-5.8.4 -d
Das anschließende make install
wird die Distribution unter dem
angegebenen Verzeichnis installieren, das Executable perl
wird
als $HOME/perl-installs/perl-5.8.4/bin/perl
verfügbar sein.
Für's schnelle Hin- und Herspringen wird ein symbolischer
Link perl-current
im Verzeichnis perl-installs
angelegt, um
die aktuell genutzte Installation zu bezeichnen:
cd $HOME/perl-installs ln -s perl-5.8.4 perl-current
Anschließend entfernt man /usr/bin/perl
und setzt statt dessen einen
weiteren
symbolischen Link an:
mv /usr/bin/perl /usr/bin/perl.orig ln -s $HOME/perl-installs/perl-current/bin/perl /usr/bin/perl
Dies lässt Skripts, die in der Shebang-Zeile #!/usr/bin/perl
stehen
haben, auf die aktuell gewählte Perl-Installation zugreifen.
Auch andere aus der Distribution genutzte Programme/Skripts
wie perldoc
sollte man entsprechend umbiegen.
Nach diesen Vorbereitungen kommt
das Skript in Listing sp.pl
(für switch perl) zum Einsatz:
Wie Abbildung 4 zeigt, bietet es eine Auswahl von unter $HOME/perl-installs
installierten Distributionen an, lässt den Benutzer eine auswählen
und setzt daraufhin den symbolischen Link perl-current
entsprechend
um. Praktisch!
01 #!/usr/bin/perl 02 use strict; 03 use warnings; 04 05 use File::Basename qw(basename); 06 07 my $PERL_HOME = "$ENV{HOME}/perl-installs"; 08 09 my(@versions, $count); 10 11 for (<$PERL_HOME/perl-*>) { 12 next if -l or ! -d; 13 push @versions, basename($_); 14 } 15 16 foreach my $v (@versions) { 17 print "[", ++$count, "] $v\n"; 18 } 19 20 $| = 1; 21 print "> "; 22 my $number = <>; 23 chomp $number; 24 25 die "Invalid choice" unless 26 exists $versions[$number-1]; 27 28 unlink("$PERL_HOME/perl-current") or 29 warn "unlink failed ($!)"; 30 symlink("$PERL_HOME/$versions[$number-1]", 31 "$PERL_HOME/perl-current") or 32 die "symlink failed ($!)";
Abbildung 4: Der perl-Selektor |
Nun verlangen diese vier vorgestellten Werkzeuge
allerdings einige Zusatzmodule auf der
Zielmaschine: b64.pl fordert MIME::Base64
, urlcode.pl braucht
URI::Escape
. Beide sind nicht in der Standard-Perl-Distribution
enthalten und darum mit einiger Wahrscheinlichkeit nicht auf der Zielmaschine
installiert.
Um alle vier heute vorgestellten Skripts einfach zu verpacken genügt es,
das mit der PAR
-Distribution vom CPAN
daherkommende Programm pp
aufzurufen:
pp --output=toolbox.exe b64.pl urlcode.pl hd.pl sp.pl
Dies erzeugt ein Binary toolbox.exe
, das alle vier Skripts samt aller
erforderlichen Zusatzmodule enthält. Fährt die Zielmaschine dieselbe
Plattform (Linux in diesem Fall), installiert sich der Werkzeugkoffer
folgendermaßen im Verzeichnis toolbox
unterhalb des
persönlichen bin
-Verzeichnisses:
mkdir ~/bin/toolbox cp toolbox.exe ~/bin/toolbox cd ~/bin/toolbox for i in b64 urlcode hd sp done ln -s toolbox $i done export PATH=$PATH:~/bin/toolbox
Die symbolischen Links unter den neuen Skriptnamen zeigen alle auf
toolbox.exe
und PAR findet selbst heraus, was gemeint ist, wenn
der Benutzer jetzt zum Beispiel b64
aufruft. Es wird b64.pl
aus
dem Archiv extrahieren, die von ihm geforderten Zusatzmodule ebenfalls
aus dem Archiv laden und das Skript ohne Murren ausführen.
PAR unterstützt sogar mehrere Plattformen gleichzeitig, man muss die
Werkzeuge nur mit der Option --multiarch
unter den
verschiedenen Betriebssystemen nacheinander in die Kiste packen.
Das Tutorial, das PAR
als PAR::Tutorial
beiliegt, zeigt, wie's
im Einzelnen geht.
Eines ist zu beachten: man sollte den Koffer auf einer möglichst alten
Installation packen, sonst kann es sein, dass es auf einer neuen Zielmaschine
Probleme mit einer älteren libc
gibt.
Packt eure Werkzeugkoffer!
Michael Schilliarbeitet als Web-Engineer für AOL/Netscape in Mountain View, Kalifornien. Er hat "Goto Perl 5" (deutsch) und "Perl Power" (englisch) für Addison-Wesley geschrieben und ist unter mschilli@perlmeister.com zu erreichen. Seine Homepage: http://perlmeister.com. |