[Cologne-pm] script auf mehreren CPU's starten

A. Pagaltzis pagaltzis at gmx.de
Thu Nov 10 10:30:14 PST 2005


Hi Cem,

* Cem Sakaryali <cem.sakaryali at easi.de> [2005-11-10 11:55]:
> Meine Frage ist, da die einzelne Dir's mitteinander nichts
> zutun haben wuerde ich sie parallel auf mehreren maschienen
> starten. Wie kann ich dies machen?

Auf mehreren Maschinen, oder auf mehreren CPUs? Oder… was? :-)

Ehrlich gesagt würde ich für diese Aufgabe garkein Perl
schreiben, sondern einfach Shell verwenden und die
Parallelausführung per üblicher Jobkontrolle erledigen. Diese
Aufgaben sind schliesslich der ganze Lebenssinn der Shell.

Zum Skript ein Haufen Kommentare:

> my $DirectoryWhereToPut = '/backup';

Der englische Begriff dafür ist übrigens »destination«.

> my ($stund,$min,$sec,$tag,$monat,$jahr)=get_time ();
> 
> foreach my $Dir (keys %hash) {
>     my $TarFileName =
> "$Dir"."BACKUP"."_"."$jahr"."_"."$monat"."_"."$tag\.tar";
>     CompressFile ($Dir,$TarFileName);
>     MoveFile ($TarFileName,$DirectoryWhereToPut);
> }

Das ist in vielerlei Hinsicht unschön.

Als allerallererstes: bitte Variablen nicht allein in
Anführungszeicehn setzen. Perl ist keine Shell. (Ja, es gibt
einen subtilen Unterschied – der zeigt sich zB. bei Referenzen,
die mit Anführungszeichen nicht funktionieren.)

Der Backslash ist übrigens überflüssig.

Ausserdem baust du den immer gleichen String aus denselben
drei von sechs Variablen zusammen – die anderen drei werden
garnicht verwendet. Schöner ist es, weniger Code zu schreiben,
indem du einfach die POSIX-Funktion `strftime` verwendest – sowas
wie ein `printf` für Datums- und Zeitangaben.

Und ausserdem: ist es deine Absicht, dass zwischen $Dir und dem
String »BACKUP« kein Verzeichnistrenner steht? Im Grossen und
Ganzen ist es anzuraten, Pfade mit den Funktionen aus File::Spec
zusammenzubauen, statt sie mit blossen String-Operationen
zusammenzukleben.

> sub CompressFile {
>     my ($Dir,$TarFileName) =@_;
>     # gzip it
>     system ("gzip -rf $Dir/\*");
>     print "gzip $Dir done\n";
>     # tar it
>     system ("tar cvf $TarFileName $Dir/\*");
>     print "tar $TarFileName done\n";
>     return;
> }

Warum gzippst du die Dateien alle einzeln und packst sie dann in
einen unkomprimierten Tarball? Wäre es andersrum nicht viel
sinnvoller?

> sub MoveFile {
>     my ($TarFileName,$DirectoryWhereToPut) =@_;
>     # move it to DirectoryWhereToPut
>     system ("mv $TarFileName $DirectoryWhereToPut");
>     print "move $TarFileName to $DirectoryWhereToPut done\n";
>     return;
> }

`system( $langer_string )` ist unschön. Enthalten deine
Dateinamen zufällig mal Leerzeichen oder andere Metazeichen, hast
du ein Problem. Eindeutig und sicher ist
`system( $programm, @parameter )`.

> sub get_time {
>     my ($sec,$min,$stund,$tag,$monat,$jahr,$junk,$day_of_year)=localtime();
>     $tag=  sprintf "%2.2d",$tag;
>     $monat=sprintf "%2.2d",$monat+1;
>     return ($stund,$min,$sec,$tag,$monat,($jahr+1900));
> }

Anmerkung am Rande: du kannst auch einfach `%2d` schreiben – ich
glaube nicht, dass du tatsächlich an Nachkommastellen
interessiert bist…

Summa summarum würde ich dieses Skript so oder ähnlich schreiben:

    #!/usr/bin/perl
    use strict;
    use warnings;

    use Getopt::Long;
    use POSIX qw( strftime );

    GetOptions(
        'destdir|d=s' => \( my $opt_destination = '/backup' ),
        'srcdir|s=s'  => \( my %opt_srcdir ),
    );

    if( not %opt_srcdir ) {
        %opt_srcdir = (
            # directory name    directory where to put
            a  => 'cem/a'  ,
            b  => 'cem/b'  ,
            c  => 'cem/c'  ,
            d  => 'cem/d'  ,
        );
    }

    my $ymd = strftime '%Y_%m_%d', localtime;

    foreach my $dir ( keys %opt_srcdir ) {
        my $tarball = "${dir}BACKUP_${ymd}.tar.gz";
        run_cmd( tar => 'cvzf', $tarball, $dir );
        run_cmd( mv => $tarball, $opt_destination );
    }

    sub run_cmd {
        system { $_[ 0 ] } @_;
        print "Done: @_\n";
    }

(Code ohne Gewähr.)

Das ist etwas hakelig, weil dein Mapping-Hash noch nicht richtig
verwendet wird… aber naja, es ist halt zu erkennen, wie es
aussehen sollte.

Um es richtig rund zu machen fehlen da jetzt noch etwas POD und
ein paar Aufrufe von Pod::Usage.

Gruss,
-- 
#Aristoteles
*AUTOLOAD=*_=sub{s/(.*)::(.*)/print$2,(",$\/"," ")[defined wantarray]/e;$1};
&Just->another->Perl->hacker;


More information about the Cologne-pm mailing list