kodo has asked for the wisdom of the Perl Monks concerning the following question:
package myftp; # myFTP is simply a frontend to the Net::FTP modules # I've written this to simplify all those FTP-Transfers here, so th +at I have a nice overview what happened (stats()) and easy error-catc +hing # The idea is to have all warnings etc saved, and not print while t +hings are called, but have a nice formatted statistic when it quits. # Some functions still need to be done like rename() etc, they curr +ently aren't in because I don't need them but I plan to put in even m +ore stuff # But primary this was just something for me to learn a bit about h +ow OO-Perl works...but maybe some other people find it usefull, too.. +. # Errormessages can be accessed via $ftp->{'errormsg'}. # # myFTP usage: # ~~~~~~~~~~~ # use myftp; # my $ftp = new myftp ( host => 'myhost', # Host to +connect to # port => '21', # Port to con +nect to # user => 'myuser', # username fo +r login # pw => 'mypassword', # password +for login # timeout => '20', # default +is 30 # retries => '3', # How o +ften should an action be retried if it fails? # verbose => '0', # Verbo +se-Level: 0 = no warnings, no failures # + 1 = no warnings, failures printed # + 2 = warnings and failures printed # + 3 = same as 2 + more details # debug => '0', # Use Net +::FTP-Debug mode? (default 0) # stats => '1', # Print s +tats when object is DESTROYed? # # $ftp->get('remotefile', 'localfile') || die "couldn't get remotef +ile: $self->{'errormsg'}; # $ftp->put('localfile', 'remotefile'); # $ftp->ls('remotefile'); # $ftp->dir('remotefile'); # $ftp->delete('remotefile'); # $ftp->stats(); # # use strict; use Net::FTP; use Carp; sub new { my $proto = shift; my $class = ref($proto) || $proto; my $self = {}; my %arg = @_; $self->{'host'} = defined($arg{'host'}) ? $arg{'host'} + : do { carp "No host specified!"; return undef; }; $self->{'port'} = defined($arg{'port'}) ? $arg{' +port'} : 21; $self->{'user'} = defined($arg{'user'}) ? $arg{'us +er'} : do { carp "No user specified!"; return undef; }; $self->{'pw'} = defined($arg{'pw'}) ? $arg{'pw'} + : do { carp "No password(pw) specified!"; return undef; }; $self->{'timeout'} = defined($arg{'timeout'}) ? $arg{'t +imeout'} : 30; $self->{'retries'} = defined($arg{'retries'}) ? $arg{'re +tries'} : 0; $self->{'verbose'} = defined($arg{'verbose'}) ? $arg{'ve +rbose'} : 1; $self->{'debug'} = defined($arg{'debug'}) ? $arg{'debug' +} : 0; $self->{'stats'} = defined($arg{'stats'}) ? $arg{'stats' +} : 1; $self->{'files_ok'} = {}; $self->{'files_failed'} = {}; $self->{'sub_warnings'} = []; $self->{'failures'} = 0; $self->{'warnings'} = 0; $self->{'errormsg'} = ''; $self->{'connected'} = ''; $self->{'start_time'} = scalar(localtime); $self->{'ftp'} = ''; $SIG{__WARN__} = sub { push(@{ $self->{'sub_warnings'} }, shift); +} if $self->{'verbose'} == 0; bless ($self, $class); { my $ok = 0; my $counter = -1; my $start_time = time; do { unless ($self->{'ftp'} = Net::FTP->new($self->{'host'}, Po +rt => $self->{'port'}, Timeout => $self->{'timeout'}, Debug => $self- +>{'debug'})) { carp "Couldn't connect to $self->{'host'}" if $self->{ +'verbose'} > 1; $self->{'warnings'}++; $counter++; } else { $self->{'time'}{'connect'} = (time - $start_time); print "Connection to $self->{'host'} established.\n" i +f $self->{'verbose'} > 2; $ok++; } } while ($counter < $self->{'retries'} && $ok == 0); do { carp "Couldn't connect to $self->{'host'}"; return undef; + } if $ok == 0; } { my $ok = 0; my $counter = -1; my $start_time = time; do { unless ($self->{'ftp'}->login($self->{'user'}, $self->{'pw +'})) { carp "Couldn't login to $self->{'host'}: FTP-Error ".$ +self->{'ftp'}->code()." : ".$self->{'ftp'}->message() if $self->{'ver +bose'} > 1; $self->{'warnings'}++; $counter++; } else { $self->{'time'}{'login'} = (time - $start_time); print "Login accepted to $self->{'host'}.\n" if $self- +>{'verbose'} > 2; $ok++; } } while ($counter < $self->{'retries'} && $ok == 0); do { carp "FTP Failed: Couldn't login to $self->{'host'}"; ret +urn undef; } if $ok == 0; } return $self; } sub DESTROY { my $self = shift; $self->{'ftp'}->quit() if defined($self->{'ftp'}); print $self->status() if $self->{'stats'} > 0; } sub status { my $self = shift; my @data = ("##################".("#" x length(scalar(localtime))) +."\n", "# myFTP Stats \@ ".scalar(localtime)." #\n", "##################".("#" x length(scalar(localtime))) +."\n\n", sprintf("%-23s %s %s", 'Started:', $se +lf->{'start_time'}, "\n"), sprintf("%-23s %s %s", 'Remote host:', $sel +f->{'host'}.":".$self->{'port'},"\n"), sprintf("%-23s %s %s", 'User:', $se +lf->{'user'}, "\n\n"), sprintf("%-23s %s %s", 'Warnings:', $self- +>{'warnings'}, "\n"), sprintf("%-23s %s %s", 'Failures:', $self- +>{'failures'}, "\n\n"), sprintf("%-23s %s %s", 'Connect-Time (secs):', $se +lf->{'time'}{'connect'}, "\n"), sprintf("%-23s %s %s", 'Login-Time (secs):', $self +->{'time'}{'login'}, "\n\n") ); push(@data, (scalar(keys %{ $self->{'files_ok'} })." files transfe +red\n", "=================".("=" x length(scalar(keys %{ $self->{'fil +es_ok'} })))."\n")); foreach (keys %{ $self->{'files_ok'} }) { $self->{'files_ok'}{$_} > 59 ? push(@data, "$_ in ".($self->{' +files_ok'}{$_} / 60)." minute(s)\n") : push(@data, "$_ in $self->{'fi +les_ok'}{$_} second(s)\n"); } push(@data, ("\n".scalar(keys %{ $self->{'files_failed'} })." file +s not transfered\n", "=====================".("=" x length(scalar(key +s %{ $self->{'files_failed'} })))."\n")); push(@data, "$_ : $self->{'files_failed'}{$_}") foreach (keys %{ $ +self->{'files_failed'} }); push(@data, ("\n".scalar(keys %{ $self->{'time'}{'commands'} })." +other commands done\n", "====================".("=" x length(scalar(k +eys %{ $self->{'time'}{'commands'} })))."\n")); push(@data, "Time(secs) for: $_: $self->{'time'}{'commands'}{$_}\n +") foreach keys %{ $self->{'time'}{'commands'} }; push(@data, ("\n".scalar(@{ $self->{'sub_warnings'} })." unexpecte +d warnings\n", "====================".("=" x length(scalar(@{ $self-> +{'sub_warnings'} })))."\n")); push(@data, $_) foreach(@{ $self->{'sub_warnings'} }); return @data; } sub error { my $self = shift; my $msg = shift; my $file = shift; $self->{'errormsg'} = $msg; $self->{'failures'}++; $self->{'files_failed'}{$file} = $msg if $file; warn $msg if $self->{'verbose'} > 0; return; } sub dir { my $self = shift; my $dir = shift || do { $self->error("dir() needs dir/file as +parameter!"); return undef; }; my @dir = (); { my $ok = 0; my $counter = -1; my $start_time = time; do { unless (@dir = $self->{'ftp'}->dir($dir)) { carp "Couldn't list(dir) $dir: ".$self->{'ftp'}->code( +).": ".$self->{'ftp'}->message() if $self->{'verbose'} > 1; $self->{'warnings'}++; $counter++; } else { $self->{'time'}{'commands'}{"dir($dir)"} = (time - $st +art_time); $ok++; } } while ($counter < $self->{'retries'} && $ok == 0); do { $self->error("Couldn't list(dir) $dir: ".$self->{'ftp'}-> +code().": ".$self->{'ftp'}->message()); return undef; } if $ok == 0; } return @dir; } sub ls { my $self = shift; my $dir = shift || do { $self->{'errormsg'} = "ls() needs dir/ +file as parameter!"; return undef; }; my @dir = (); { my $ok = 0; my $counter = -1; my $start_time = time; do { unless (@dir = $self->{'ftp'}->ls($dir)) { carp "Couldn't list(ls) $dir: ".$self->{'ftp'}->code() +.": ".$self->{'ftp'}->message() if $self->{'verbose'} > 1; $self->{'warnings'}++; $counter++; } else { $self->{'time'}{'commands'}{"ls($dir)"} = (time - $sta +rt_time); $ok++; } } while ($counter < $self->{'retries'} && $ok == 0); do { $self->error("Couldn't list(ls) $dir: ".$self->{'ftp'}->c +ode().": ".$self->{'ftp'}->message()); return undef; } if $ok == 0; } return @dir; } sub size { my $self = shift; my $file = shift || do { $self->{'errormsg'} = "size() needs file +as parameter!"; return undef; }; my $size = ''; { my $ok = 0; my $counter = -1; my $start_time = time; do { unless($size = grep_size($self->{'ftp'}->dir($file))) { carp "Couldn't get size of $file:".$self->{'ftp'}->cod +e().": ".$self->{'ftp'}->message() if $self->{'verbose'} > 1; $self->{'warnings'}++; $counter++; } else { $self->{'time'}{'commands'}{"size($file)"} = (time - $ +start_time); $ok++; } } while ($counter < $self->{'retries'} && $ok == 0); do { $self->error("Couldn't get size of $file: ".$self->{'ftp' +}->code().": ".$self->{'ftp'}->message()); return undef; } if $ok == +0; } sub grep_size { my $size; foreach(@_) { ($size) = $_ =~ /^.*?\s+.*?\s+.*?\s+.*?\s+(.*?)\s.*?/; } return $size if $size =~ /^\d*$/; return undef; } return $size; } sub delete { my $self = shift; my $file = shift || do { $self->{'errormsg'} = "delete() needs fil +e as parameter!"; return undef; }; { my $ok = 0; my $counter = -1; my $start_time = time; do { unless ($self->{'ftp'}->delete($file)) { carp "Couldn't delete $file: ".$self->{'ftp'}->code(). +": ".$self->{'ftp'}->message() if $self->{'verbose'} > 1; $self->{'warnings'}++; $counter++; } else { $self->{'time'}{'commands'}{"delete($file)"} = (time - + $start_time); $ok++; } } while ($counter < $self->{'retries'} && $ok == 0); do { $self->error("Couldn't delete $file: ".$self->{'ftp'}->co +de().": ".$self->{'ftp'}->message()); return undef; } if $ok == 0; } return 1; } sub put { my $self = shift; my %arg = @_; my $localfile = $arg{'localfile'} || do { $self->{'errorms +g'} = "put() needs (localfile,remotefile) as parameters!"; return und +ef; };; my $remotefile = $arg{'remotefile'} || do { $self->{'error +msg'} = "put() needs (localfile,remotefile) as parameters!"; return u +ndef; };; my $mode = $arg{'mode'} || 'binary'; { my $ok = 0; my $counter = -1; my $start_time = time; do { unless ($self->{'ftp'}->$mode()) { carp "Couldn't set mode to $mode!: ".$self->{'ftp'}->c +ode().": ".$self->{'ftp'}->message() if $self->{'verbose'} > 1; $self->{'warnings'}++; $counter++; } else { $ok++; } } while ($counter < $self->{'retries'} && $ok == 0); do { $self->error("Couldn't upload $localfile as $remotefile: +Couldn't change mode to $mode: ".$self->{'ftp'}->code().": ".$self->{ +'ftp'}->message(), "$localfile => $remotefile"); return undef; } if $ +ok == 0; } { my $ok = 0; my $counter = -1; my $start_time = time; do { unless ($self->{'ftp'}->put($localfile, $remotefile)) { carp "Couldn't upload $localfile as $remotefile: ".$se +lf->{'ftp'}->code().": ".$self->{'ftp'}->message() if $self->{'verbos +e'} > 1; $self->{'warnings'}++; $counter++; } else { $self->{'files_ok'}{"$localfile => $remotefile"} = (ti +me - $start_time); $self->{'files'}++; $ok++; } } while ($counter < $self->{'retries'} && $ok == 0); do { $self->error("Couldn't upload $localfile as $remotefile: +".$self->{'ftp'}->code().": ".$self->{'ftp'}->message(), "$localfile +=> $remotefile"); return undef; } if $ok == 0; } return 1; } sub get { my $self = shift; my %arg = @_; my $remotefile = $arg{'remotefile'} || do { $self->{'error +msg'} = "put() needs (localfile,remotefile) as parameters!"; $self->{ +'failures'}++; return undef; };; my $localfile = $arg{'localfile'} || do { $self->{'errorms +g'} = "put() needs (localfile,remotefile) as parameters!"; $self->{'f +ailures'}++; return undef; };; my $mode = $arg{'mode'} || 'binary'; { my $ok = 0; my $counter = -1; my $start_time = time; do { unless ($self->{'ftp'}->$mode()) { carp "Couldn't set mode to $mode!: ".$self->{'ftp'}->c +ode().": ".$self->{'ftp'}->message() if $self->{'verbose'} > 1; $self->{'warnings'}++; $counter++; } else { $ok++; } } while ($counter < $self->{'retries'} && $ok == 0); do { $self->error("Couldn't download $remotefile as $localfile +: Couldn't change mode to $mode: ".$self->{'ftp'}->code().": ".$self- +>{'ftp'}->message(), "$remotefile => $localfile"); return undef; } if + $ok == 0; } { my $ok = 0; my $counter = -1; my $start_time = time; do { unless ($self->{'ftp'}->get($remotefile, $localfile)) { carp "Couldn't download $remotefile as $localfile!" if + $self->{'verbose'} > 1; $self->{'warnings'}++; $counter++; } else { $self->{'files_ok'}{"$localfile => $remotefile"} = (ti +me - $start_time); $self->{'files'}++; $ok++; } } while ($counter < $self->{'retries'} && $ok == 0); do { $self->error("Couldn't download $remotefile as $localfile +: ".$self->{'ftp'}->code().": ".$self->{'ftp'}->message(), "$remotefi +le => $localfile"); return undef; } if $ok == 0; } return 1; } 1;
|
|---|