FeistyLemur has asked for the wisdom of the Perl Monks concerning the following question:

Everything I've read about Net::FTP leads me to believe what I'm doing with it should be correct, but it clearly is not, as I'm getting one exception that kills my entire script in specific conditions.

I'm connecting to a series of devices via ftp to upload and burn a firmware file. In some rare instances, the FTP connection could be successfully established, and upload of the file can begin, but then the device could lose connectivity or simply time out the process.

The documentation says do this...

my $user='user'; my $password='pass'; my $file='/path/file'; my $ftp=Net::FTP->new($client, Timeout => 30, Passive => 1) or die "C +ould not Connect.\n"; $ftp->login ($user, $password); $ftp->binary; $ftp->put($file) or die "Error Uploading.\n"; $ftp->quit;

if connection is lost during the $ftp->put($file) or the device just pukes and it times out, the whole script pukes and drops a timeout error from the module itself. What am I doing wrong with how I'm doing this?

EDITED: Yes $pass was a typo only in the example above, corrected to $password. I do use strict and warnings and the code otherwise runs flawlessly other than the issue I very rarely have with timeouts.

Replies are listed 'Best First'.
Re: Net::FTP Question.
by hippo (Archbishop) on Aug 13, 2015 at 18:07 UTC

    Your call to login uses the variable $password which you have not set. I fail to see how you could possibly be connecting at all with this code unless your servers accept anonymous access. Or is the code above not the code you are running?

    Addendum: Perhaps an SSCCE would be helpful?

      It is, but I typed the declarations manually and I made a typo on "my $pass" which should be "my $password". The actual non example code does indeed run properly, save for the behavior I'm asking about.

Re: Net::FTP Question.
by runrig (Abbot) on Aug 13, 2015 at 18:25 UTC

    I'll assume the password variable above is a typo, and that you do Use strict and warnings. Instead of die'ing, you can simply retry the whole process if it does not succeed (reconnect, login, put).

    You can also include the reason for any failure in any warning messages ($@ on connect, $ftp->message() on any other method) if desired.

Re: Net::FTP Question.
by stevieb (Canon) on Aug 13, 2015 at 19:26 UTC

    I'm guessing that you've got this code in a loop, and run it once per client. If this is the case, take a look at the below code. It uses an eval block to catch any errors per each client, and if it fails, it will print a notice and per runrig's suggestion, retry two more times before giving up and moving on to the next client.

    #!/usr/bin/perl use warnings; use strict; use Net::FTP; my $user='steve'; my $password='...'; my $file='re.pl'; my @clients = qw(localhost example.com); for my $client (@clients){ for (1..3){ my $ftp; eval { $ftp=Net::FTP->new( $client, Timeout => 2, Passive => 1 ) or die "Could not Connect.\n"; $ftp->login ($user, $password); $ftp->binary; $ftp->put($file) or die "Error Uploading.\n"; print "$client done on attempt $_\n"; $ftp->quit; }; last if ! $@; print "$client broke on attempt $_\n"; } } __END__ $ ./ftp.pl localhost done on attempt 1 example.com broke on attempt 1 example.com broke on attempt 2 example.com broke on attempt 3

      More or less, yes, I have it in a sub that also connects via telnet to the device and runs a burn command which gets called by a loop, and attempts to return whether successful.

      But yes that looks to be just what I was looking for, I'll give eval a go and see how it works out, Thanks for the info.