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