perl script

Giorgos Keramidas keramida at ceid.upatras.gr
Wed Mar 26 02:18:04 EET 2003


On 2003-03-26 01:00, Pavlos Parissis <p_pavlos at freemail.gr> wrote:
> Καλησπέρα,
> Έχω φτιάξει ένα απλό perl script το οποίο προσθέτει την επιλογή
> "logging" στα ufs filesystems μέσα σε ένα solaris /etc/vfstab.
> Αλλά κάποιο λόγο που έχω εδώ 2 ώρες που προσπαθώ δεν τον έχω βρει δεν
> δουλεύει.

Άμα σου πήρε 2 ώρες για να γράψεις αυτό το πράγμα που δεν ελέγχει
σχεδόν τίποτα για λάθη, συγγνώμη κιόλας, αλλά γιατί γράφεις Perl;

> ###########################
> use warnings;
> use strict;
>
> my $file;
> my $lines;
> my @fields;
> my $temp_line;
>
> $file="vfstab";
>
> open (FOUT, ">$file.out");
> open (FIN, "$file") or die "ATTENTION: The /etc/vfstab does not exists: $!\n";

Bullshit!  Αφού το αρχείο που προσπαθείς να κάνεις open() δεν είναι το
/etc/vfstab αλλά το "vfstab" (χωρίς full path), γιατί λες αηδίες στον
user στο μήνυμα λάθους;

Ο σωστός τρόπος είναι να κάνεις κάτι σαν:

	my $vfstab = "/etc/vfstab";

	open(VFSTAB, "$vfstab") || die "open";

Ένα άλλο μελανό σημείο είναι ότι το script ανοίγει το FOUT πριν καν
δοκιμάσει να ανοίξει το FIN.  Αυτό έχει δυο πιθανά προβλήματα:

α) Αφενός δεν ελέγχεις αν το open(FOUT, ...) πέτυχε ή όχι.

β) Δεν κάνεις κάποιο έλεγχο παρακάτω να σιγουρευτείς ότι
   τουλάχιστον μια γραμμή γράφεται στο $file.out και μπορεί να
   καταλήξεις να κάνεις μια προσπάθεια για overwrite του $file
   με το $file.out και να σβήσεις ουσιαστικά το $file.

> foreach $lines (<FIN>){
>    chop($lines);

Καλύτερα είναι να χρησιμοποιείς την chomp(); Επίσης, είναι καλή ιδέα
όταν γράφεις με 'strict' και 'warnings' ενεργοποιημένα να
προγραμματίζεις με ασφαλή τρόπο.  Στο παραπάνω, τι γίνεται όταν το
$line == undef επειδή το <FIN> έφτασε στο end of file του;

Σου προτείνω να χρησιμοποιήσεις τουλάχιστον ένα έλεγχο defined($line)
κάπου εκεί πέρα, για να μη σου πω να το γράψεις όπως όλος ο καλός
κόσμος και όχι με αυτή την αηδία του foreach:

	my $lc = 0;
	while (defined($line = <FIN>)) {
		chomp $line;
		$lc++;

		@ary = split /\s+/, $line;
		die "Missing fields in line $lc of $vfstab\n"
		  if ($#ary != 6);

		...

	}

>    @fields = split /\s+/, $lines;
>    print "$fields[3]\n";

Εδώ τυπώνεις μόνο το πεδίο [3].  Δεν τυπώνεις τα πεδία [0] - [3].

>    if ($fields[3] eq "ufs" and $fields[6] ne "logging"){

Γιατί λυπάσαι τις παρενθέσεις και δεν λυπάσαι τονν εαυτό σου που θα
ψάχνεσαι μετά από λίγο γιατί κάνει βλακείες το πρόγραμμα; Α συγγνώμη,
ήδη ψάχνεσαι...

>        if ($fields[6] eq "-"){
>            $fields[6] = "logging";
>        }
>        else {
>            $fields[6] = "$fields[6]". ",logging";
>        }

Πως είσαι τόσο εξοργιστικά σίγουρος ότι ΥΠΑΡΧΕΙ πεδίο [6];

>    }
>
>    foreach $temp_line (@fields){
>    print FOUT "$temp_line ";
>    }

Λάθος τρόπος να τυπώνεις πεδία.  Μάθε τη join().

>    print FOUT "\n";
> }
> close(FIN);
> close(FOUT);
> #system("/bin/cp $file\{,.bak\}");
> #system("/bin/rm $file");
> #system("/bin/mv $file.out $file");

Αυτά τα τελευταία ΟΥΤΕ ΠΟΥ ΝΑ ΣΟΥ ΠΕΡΑΣΕΙ ΑΠΟ ΤΟ ΜΥΑΛΟ να τα κάνεις
uncomment.  Αν θες το καλό σου, πέτα το όλο το script όπως είναι και
κοίτα στο τέλος του mail.  Κι όταν κάνεις κάτι σε πρόγραμμα που μπορεί
να αποτύχει, *ΠΑΝΤΑ* να ελέγχεις αν πέτυχε ή όχι και γιατί.

> ###############################
>
> το αρχείο vfstab έχει αυτά:
>
> fd - /dev/fd fd - no -
> /proc - /proc proc - no -
> /dev/md/dsk/d2 - - swap - no -
> /dev/md/dsk/d1 /dev/md/rdsk/d1 / ufs 1 no -
> /dev/md/dsk/d3 /dev/md/rdsk/d3 /opt ufs 2 yes -
> swap - /tmp tmpfs - yes size=512m
>
> και όταν το τρέχω πέρνω [...]

Ορίστε η έξοδος από το filter που θα βρεις παρακάτω:

	giorgos at gothmog[02:15]/tmp$ perl lala.pl < vfstab
	fd - /dev/fd fd - no -
	/proc - /proc proc - no -
	/dev/md/dsk/d2 - - swap - no -
	/dev/md/dsk/d1 /dev/md/rdsk/d1 / ufs 1 no logging
	/dev/md/dsk/d3 /dev/md/rdsk/d3 /opt ufs 2 yes logging
	swap - /tmp tmpfs - yes size=512m

Και φυσικά, είναι filter και δεν προσπαθεί να κάνει παπάδες σε ένα
quick and dirty script με file open και redirects και system() κλήσεις
στο shell για να κάνει ένα απλό rename.  Jesus!...

    #!/usr/bin/perl

    use warnings;
    use strict;

    my $lc = 0;                     # current line number
    my $line = undef;
    my @ary = undef;
    while (defined($line = <STDIN>)) {
        chomp $line;
        $lc++;

        @ary = split /\s+/, $line;
        die "Missing fields in line $lc\n"
            if ($#ary != 6);
        if ($ary[3] eq "ufs") {
            if ($ary[6] eq "-") {
                $ary[6] = "logging";
            } else {
                $ary[6] .= ",logging";
            }
            $line = join(" ", @ary);
        }
        print "$line\n";
    }

----------------------------------------------------------------------------
EOP ::= End of Perls




More information about the Linux-greek-users mailing list