Raj,
Check out the Net::FTP documentation. Most
ftp methods return undef on failure. So check after each
operation. Wraping in eval will also help.
eval {
$ftp = Net::FTP->new("mysys",Port => 9021,
Timeout => 20,
Debug => 0)
or die "Cannot create ftp object";
$ftp->login("anonymous",'me@myself.com')
or die "Cannot login";
$ftp->put("$dir/$file1")
or die "Cannot put";
$ftp->put("$dir/$file2")
or die "Cannot put";
$ftp->put("$dir/$file3")
or die "Cannot put";
$ftp->quit;
}
if( $@ ) {
print "We had an issue: ", $@, "\n";
} else {
print "A-Okay";
}
I don't see an mput type method, but it should be real
trivial to code:
@files = qw( $file1 $file2 $file3 );
foreach( @files ) {
$ftp->put( $_ )
or die "Cannot put";
}
-derby | [reply] [d/l] [select] |
Hello,
Yeah, the Net::FTP docs seem kind of lacking on this information. While I haven't tried the following answers out for myself, I got them from a program which works, so I'd assume they are correct:
1. when FTP->new() call was invoked
Well, this is just a typical constructor, the FTP code hasn't tried to do anything with a remote system yet. However, you can check for the return value of the login() call, like so:
my $max_tries = 5;
my $tries = 0;
# login() returns false, if unsuccessful
while( ! $ftp->login('anonymous', 'me@myself.com' ) {
$tries++;
die "We tried $tries times, but cannot connect!\n" if $max_tries ==
+$tries;
warn "Attempt $tries: Could not connect, trying again.\n";
}
print "Yay! We logged in!\n";
2. when all the files were ftp'd. i.e., at FTP->quit
The return value of $ftp->quit would actually tell you if the quit() call was successful or not, which isn't what I think you're worried about.
What you'd need to do is check the call of each put() method:
$ftp->put("$dir/$file1") or die "FTP did not succesfully upload $dir/
+$file!";
Or, if you don't actually want to die, you could also just set a flag if the put fails. Just like login(), put returns a true value if successful, false otherwise.
Hope that helps!
-Eric
Update: Yeah, what derby said, he managed to type it in quicker then myself, and I like his eval trick :-)
--
Lucy: "What happens if you practice the piano for 20 years and then end up not being rich and famous?"
Schroeder: "The joy is in the playing." | [reply] [d/l] [select] |
The mput command is not implemented in Net::FTP, even though the documentation doesn't explicitly state the fact.
You can check $! for errors after a put, but from experience, this only relates to problems on the local host (e.g. "file not found"). To be absolutely certain that the file was tranferred to the remote host you could always do a dir and check the size of the remote file (modulo different sizes if transferring in ASCII between Unix and MS-DOS etc.).
You could gain a bit of clarity (and, possibly, encapsulate stuff) by using a loop:
for my $file ( $file1, $file2, $file ) {
my $f = "$dir/$file";
$ftp->put( $f ) or warn "could not put $f: $!\n";
my $remote_size = get_remote_size( $f );
my $local_size = -s $f;
if( $remote_size != $local_size ) {
warn "$f not transferred correctly (local=$local_size, remote=$rem
+ote_size)\n";
}
}
... where the routine get_remote_size is left as an exercise to the reader. Hmmm... I should have read giant's post more carefully. The code presented there appears to do just that.
print@_{sort keys %_},$/if%_=split//,'= & *a?b:e\f/h^h!j+n,o@o;r$s-t%t#u' | [reply] [d/l] |
lo Raj,
I've had similar problems and I've finally done it this way:
use Net::FTP;
use Net::Ping;
# Calling the subs...:
# Checking if host is up...
sub pingcheck {
my $host = shift;
if ($ping->ping($host)) {
return 0;
} else {
print "$host is dead...\n";
return 1;
}
}
# Connect to Server...
sub connectftp {
my $host = $_[0];
unless ($ftp = Net::FTP->new($host, Timeout => 6, Debug => 0)) {
print "Couldn't connect to $host\n";
return 1;
}
return 0;
}
# Do login...
sub loginftp {
my ($user, $pw) = @_;
unless ($ftp->login($user, $pw)) {
print "Couldn't login\n";
return 1;
}
return 0;
}
# Set transfer-mode
sub modeftp {
my $mode = shift;
if ($mode eq 'B') { $mode = "binary"; }
elsif ($mode eq 'A') { $mode = "ascii"; }
elsif ($mode eq 'E') { $mode = "ebcdic"; }
elsif ($mode eq "Y") { $mode = "byte"; }
else { $mode = "binary"; }
unless ($ftp->$mode()) {
print "Couldn't set transfermode to $mode!\n";
return 1;
}
print "$mode\n";
return 0;
}
# Now here we have the GET-Part, it supports *.txt also (mget), and yo
+u can even check if the sizes of remote and local-file are equal (onl
+y makes sense with binary data often)
sub getftp {
my ($file, $localfile) = @_;
my ($remotesize, $localsize) = '';
my @files = ();
if (! $localfile) { $file =~ /.*\/(.*)$/; $localfile .= $1; }
if ($localfile =~ /\/$/) { $file =~ /.*\/(.*)$/; $localfile .= $1;
+ }
if ($file =~ /\*/) {
unless (@files = $ftp->ls($file)) {
print "Couldn't download $file as $localfile: $file does n
+ot exist?!\n";
return 2;
}
} else {
push(@files, $file);
}
foreach $file (@files) {
if (! $localfile) { ($localfile) = $file =~ /.*\/(.*)$/; }
unless (@_ = $ftp->ls($file)) {
print "Couldn't download $file as $localfile: $file does n
+ot exist?!\n";
return 2;
}
unless ($ftp->get($file, $localfile)) {
print "Couldn't download $file as $localfile!\n";
return 1;
}
if ($checksize == 1) {
$localsize = ((stat($localfile))[7]);
foreach($ftp->dir($file)) { ($remotesize) = $_ =~ /^.*?\s+
+.*?\s+.*?\s+.*?\s+(.*?)\s.*?/; }
if ($localsize ne $remotesize) {
print "Failure while downloading $file as $localfile:
+Sizecheck failed ($localsize != $remotesize)!\n";
return 1;
}
}
print "Downloaded $file\n";
}
return 0;
}
I hope this helps you a bit, the code can for sure be optimized but it's a pretty good way I think to check if everything went right...
Greets,
giant_
-----BEGIN PERL GEEK CODE BLOCK-----
Version: 0.01
P++>+++$c-> P6 >+R+>+M+>++O
>+MA+>+++E+>++PU+>+++BD C+>++D!S X!WP
>+++MO?PP++n CO?PO-o+G
A--OL!Ee---Ev++Eon!Eot!Eob!Eoa!uL++uB
uS!uH+uo+w---m!osA-osBE-
------END PERL GEEK CODE BLOCK------ | [reply] [d/l] |
To do proper error checking after each put. I think you should check the return code explicitly and then return the error message from ftp. Here is how I would do it.
$ftp = Net::FTP->new("mysys",Port => 9021,Timeout => 20, Debug => 0);
$ftp->login("anonymous",'me@myself.com');
$ftp->put("$dir/$file1");
my $rtncode=$ftp->code;
if ($rtncode != 226 && $rtncode != 250)
{
my $msg=$ftp->message;
print "FTP Failed: $msg\n";
$ftp->quit;
}
#do remainder of your puts here.
The '226' and the '250' are both return codes used in FTP. You can read more about them in the RFC for ftp. update: to fix link
| [reply] [d/l] |