使用while循环的perl变量范围

时间:2014-05-15 01:04:46

标签: perl while-loop scope subroutine

我从我的客户端计算机上传到我的服务器的ftp上传一直作为备份方式运行,偶尔如果连接损坏,上传将停止,解决方法是删除"损坏的文件&#34 ;从服务器,然后客户端恢复,并在下次客户端运行时上载文件。此脚本用于删除之前从未发生过的文件,或检查过去是否已删除的时间戳,并检查这是否是新发生的。然后根据需要删除。

日志文件中的行将是:

Sun May 11 02:38:46 2010 [pid 17116] [ftp] FAIL UPLOAD: Client "192.168.179.58", "/Dan/Example.file", 0.00Kbyte/sec

并且一旦写入文件列表,它看起来像这样:

Sun May 11 02:38:46 - /Dan/Example.file

下面您可以看到范围问题在read_filelist()子例程中的位置。

到目前为止,请查看解决方案:

#!/usr/bin/perl
use warnings;
use strict;
use Data::Dumper qw(Dumper);

#open /var/log/vsftpd.log read only, and /var/log/vsftpd.log R/W + append
open my $logfile, '<', '/var/log/vsftpd.log'  # 3 arg open is safer
    or die "could not open file: $!"; # checking for errors is good
open my $filelist, '+<', '/scripts/filelist' 
    or die "could not open file: $!";

my @rid;
my @filename;
my @deletedfile;
my $int = -1;
my @time;
my @hourcompare;
my @splittime;
my @filelisttime;
my @splitfilelisttime;
my @filelistfile;
my @filelistarray;
my $fileexists = 0;

#Define read_filelist()
sub read_filelist{

my ($filename, $hour, $min, $sec, $filelist) =  @_;

while (<$filelist>){
        @filelisttime = split /\s+/, $_;
        @splitfilelisttime = split /:/, $filelisttime[3];
        @filelistfile = split /\s+-\s+/, $_;
        my $fsec = $splitfilelisttime[2]+0;
        my $fmin = $splitfilelisttime[1]+0;
        my $fhour = $splitfilelisttime[0]+0;

    if ($filelistfile[2] eq $filename){
                my $fileexists = 1;
                       if ($hour >= $fhour){
                                if($min >= $fmin){
                                        if($sec > $fsec){
                                                system ("rm", "-fv", "/home/desktop"."$filename");
                                                        }
                                                 }
                                        }
                                }
    }
}

#open vsftp log and look for lines that include "FAIL UPLOAD" print those lines to a file
while (<$logfile>) {
$int = $int + 1;

    if (index($_, "FAIL UPLOAD:") != -1){
     @rid =  split /\s+"/, $_;
    @filename = split /",/, $rid[2];
    @time = split /\s+201/, $rid[0]; 
    }

$deletedfile[$int] = $filename[0];
        if ($filename[0] ne $deletedfile[$int-1]){
                print $filelist $time[0]." - ".$filename[0]."\n";
           }

#convert the timestamp into integers for comparison
@hourcompare = split /\s+/, $time[0];
@splittime = split /:/, $hourcompare[3];
my $sec = $splittime[2]+0;
my $min = $splittime[1]+0;
my $hour = $splittime[0]+0;

        #itterate through '/scripts/filelist'
    read_filelist($filename[0], $hour, $min, $sec, $filelist);

    if ($fileexists = 0){
        system ("rm", "-fv", "/home/desktop"."$filename[0]");
    }
}
close $filelist;
close $logfile;

变量传递给read_filelist()子没有问题,但是当我启动while()循环时,所有传递的变量都变为未初始化:

sub read_filelist {

    my ($filename, $hour, $min, $sec, $filelist) =  @_;

    while (<$filelist>) {

        @filelisttime = split /\s+/, $_;
        @splitfilelisttime = split /:/, $filelisttime[3];
        @filelistfile = split /\s+-\s+/, $_;
        my $fsec = $splitfilelisttime[2]+0;
        my $fmin = $splitfilelisttime[1]+0;
        my $fhour = $splitfilelisttime[0]+0;

        if ($filelistfile[2] eq $filename) {
            my $fileexists = "T";
            if ($hour >= $fhour) {
                if($min >= $fmin) {
                    if($sec > $fsec) {
                        system ("rm", "-fv", "/home/desktop"."$filename");
                    }
                }
            }
        }

        print "log: " . "$hour" . ":" . "$min" . ":" . "$sec" . "\n";
        print "file: " . "$fhour" . ":" . "$fmin" . ":" . "$fsec" . "\n";
        print "$filename" . "\n";
    }
}

read_filelist($filename[0], $hour, $min, $sec, $filelist);

返回以下内容:

Use of uninitialized value in string eq at removefailed.pl line 39, <$filelist> line 1.
Use of uninitialized value $filename in string eq at removefailed.pl line 39, <$filelist> line 1.
log: 0:0:0
file: 2:38:46
Use of uninitialized value $filename in string at removefailed.pl line 52, <$filelist> line 1.

但是,如果我将打印件移到while循环之外,它可以工作,但显然我只能将它们与文件列表的最后一行进行比较。

sub read_filelist {

    my ($filename, $hour, $min, $sec, $filelist) =  @_;
    print "log: " . "$hour" . ":" . "$min" . ":" . "$sec" . "\n";

    while (<$filelist>) {
        @filelisttime = split /\s+/, $_;
        @splitfilelisttime = split /:/, $filelisttime[3];
        @filelistfile = split /\s+-\s+/, $_;
        my $fsec = $splitfilelisttime[2]+0;
        my $fmin = $splitfilelisttime[1]+0;
        my $fhour = $splitfilelisttime[0]+0;

        if ($filelistfile[2] eq $filename) {
            my $fileexists = "T";
            if ($hour >= $fhour) {
                if($min >= $fmin) {
                    if($sec > $fsec) {
                        system ("rm", "-fv", "/home/desktop"."$filename");
                    }
                }
            }
        }

        print "file: " . "$fhour" . ":" . "$fmin" . ":" . "$fsec" . "\n";
    }
    print "$filename" . "\n";
}

read_filelist($filename[0], $hour, $min, $sec, $filelist);

我得到以下输出:

file: 2:38:46
log: 2:38:46
/Dan/Example.file

如果您需要任何进一步的信息,请与我们联系。

1 个答案:

答案 0 :(得分:0)

我使用Hash解决了这个问题。我认为这是因为文件列表已经在日志文件中打开了。

无论如何我创建了一个全局哈希:

my %logfilelines;

从日志文件中将所有相关的相关行传递给它:

$logfilelines{$filename[0].":".$hour.":".$min.":".$sec}++

然后在read_file()子目录中运行%logfilelines;并比较文件名\时间等。我将不得不重建时间比较,因为它是错误的但至少我现在正在取得进展。如果您好奇,请参阅下面的新子程序:

sub read_filelist{

#my ($filename, $hour, $min, $sec, $filelist) =  @_;
my $fint = -1;
my @filelines;
my @filelistlines;

foreach my $line (keys %logfilelines) {
    open my $filelist2, '<', 'c:\scripts\filelist'
            or die "could not open file: $!";

    $fint = $fint + 1;
    $filelines[$fint] = $line;
    @filelistlines = split /:/, $filelines[$fint];
    my $filename = $filelistlines[0];
    my $hour = $filelistlines[1]+0;
    my $min = $filelistlines[2]+0;
    my $sec = $filelistlines[3]+0;

            while (<$filelist2>){

                my @filelisttime = split /\s+/, $_;
        my @splitfilelisttime = split /:/, $filelisttime[3];
        my @filelistfile = split /-\s+/, $_;
        my $fsec = $splitfilelisttime[2]+0;
        my $fmin = $splitfilelisttime[1]+0;
        my $fhour = $splitfilelisttime[0]+0;

                    chomp $filelistfile[1];

            if ($filelistfile[1] eq $filename){
                   # my $fileexists = 1;
                              print "log: "."$hour".":"."$min".":"."$sec"." $filename"."\n";
                              print "file: "."$fhour".":"."$fmin".":"."$fsec"."\n";
                           if ($min > $fmin || $hour > $fhour){
                            #        if($min >= $fmin ||$hour >= $fhour){
                          #                 if($sec > $fsec){
                                                    #system ("rm", "-fv", "/home/desktop"."$filename");
                                                                                                    print "success"." $filename";
                              #                             }
                                 #                   }
                                            }
                                    }

            }

    }