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

I wrote an automated FTP script as follows:
#!/usr/bin/perl -w use strict; use Socket; use Net::FTP; $site = 'ftp.wolfger.com'; $address = inet_ntoa(inet_aton($site))); $ftp = Net::FTP->new ( "ftp.wolfger.com", Timeout => 60 ) or die "Connection failed to $address\n"; $user = "<insert username here>"; $pass = "<insert password here>"; $ftp->login($user, $pass) or die "Login failed for $user.\n"; $ftp->cwd('./main_html'); $ftp->type('binary'); $local = "/home/wolfger/Shared/Documents/wolfger/howllog.html"; $remote = "howllog.html"; $ftp->put($local, $remote) or die "Failed to put file $remote.\n"; $ftp->quit() or die "Could not quit connection to $address\n";

The problem is that sometimes this works fine. Other times, it dies with the message "Failed to put file howllog.html." I'm at a complete loss for why it sometimes works and sometimes doesn't. One thing I do notice is that after the script is run, I have the following process running on my box:
postfix 18788 1591 0 15:58 ? 00:00:00 pickup -l -t fifo -u -c

Usually killing this process allows the script to work again, but this morning I got not get the script to run successfully at all.

Edit: Added <code> tags. larsen

Replies are listed 'Best First'.
Re: Net::FTP only working occasionally.
by Mr. Muskrat (Canon) on Mar 31, 2003 at 16:07 UTC

    First, I wouldn't kill postfix's processes if I were you.

    Second, this code will never run as is. Too many compilation errors. Are you sure that this is the code you are running?

    Add my's to each of the variable declarations, then remove the final ) from the $address declaration line. Speaking of which, what is the point of using $address here at all, when you can use $site?

    $ftp->cwd('./main.html'); is all wrong unless you have a directory called main.html.

    $ftp->type('binary'); can be rewritten as $ftp->binary(); since they are synonomous.

    Update: You might want to check for the existance of '/home/wolfger/Shared/Documents/wolfger/howllog.html' before trying to upload it.

    sometime later: /me shrugs

      Err... Uhm. Okay, I must confess. In the script I'm actually running, I deleted "use strict;"
      (I posted the script as I orignally wrote it. The actual script is at home)

      There is no point to $address. It was used simply for the sake of using it...

      The directory is main_html. Underscore, not dot.

      and yes, the source file exists. As I said, sometimes the script works. Sometimes it doesn't.

        If it sometimes works, and sometimes doesn't, you should look into the process that provides the FTP service, not your code, IMO.

        I don't have any experience with uploading files, but I'm constantly running into the same kind of error when retrieving files from an FTP server (MS IIS in my case).
        At first, I thought it was my code, when my colleague noticed the FTP server shut down his connection once in a while too. He was using IE to manually look up files.

        Our system people were not able to come up with a solution, but we did notice that this strange behaviour occurred omre frequently when network traffic was at a peak.

        So maybe you should toy around with a browser for a while and see what happens?

        Cheers,
        MichaelD

Re: Net::FTP only working occasionally.
by runrig (Abbot) on Mar 31, 2003 at 18:41 UTC
    You might want to include the last message in your error message (Net::FTP inherits from Net::Cmd, so the method is documented there), e.g.:
    $ftp->put($local, $remote) or die "Failed to put file $remote: ".$ftp->message."\n";
    Or turn on debugging (see both Net::FTP and Net::Cmd) and see what's going on.
Re: Net::FTP only working occasionally.
by Mr. Muskrat (Canon) on Mar 31, 2003 at 18:45 UTC

    Turn on debugging and see if it helps you track down the culprit.

    my $ftp = Net::FTP->new($site, Timeout => 60, debug => 1, ) or die "Connection failed to $site.\n";

    Another suggestion is to use Net::FTP's error messages instead of your own.
    $ftp->login($user, $pass) or die $ftp->message();

    Good luck!

      I put in "or die $ftp->message();" and got the error "Invalid number of arguments." the next time it died.

      Then I added "debug => 1" and... the script worked. And it worked the next 5 times I tried it. Note that I never changed the number of arguements... It just suddenly went from invalid to valid, automagically.

      I shall meditate upon this.

      This morning I noticed that the script did not work when cron called it in the middle of the night. I ran it again, and here are the two different debug outputs:
      When the script works
      Net::FTP=GLOB(0x8244e84)>>> TYPE binary
      Net::FTP=GLOB(0x8244e84)<<< 500 'TYPE binary'
      Net::FTP=GLOB(0x8244e84)>>> PORT 192,168,0,10
      Net::FTP=GLOB(0x8244e84)<<< 200 PORT command
      Net::FTP=GLOB(0x8244e84)>>> STOR howllog.html
      Net::FTP=GLOB(0x8244e84)<<< 150 Opening ASCII
      tml.
      Net::FTP=GLOB(0x8244e84)<<< 226 Transfer comp
      Net::FTP=GLOB(0x8244e84)>>> QUIT
      Net::FTP=GLOB(0x8244e84)<<< 221 Goodbye.

      When it doesn't work
      Net::FTP=GLOB(0x8244e84)>>> TYPE binary
      Net::FTP=GLOB(0x8244e84)<<< 500 'TYPE binary' not understood.
      Net::FTP=GLOB(0x8244e84)>>> PORT 192,168,0,10,222,129
      Net::FTP=GLOB(0x8244e84)<<< 501 Invalid number of arguments.

      So my questions are two-fold:
      1) Why is "TYPE binary" sometimes not recognized?
      2) How can I get my perl to keep trying until the send is successful?

      Now I have seen a third output:
      Net::FTP=GLOB(0x8244e84)>>> TYPE binary
      Net::FTP=GLOB(0x8244e84)<<< 500 'TYPE binary' not understood.
      Net::FTP=GLOB(0x8244e84)>>> PORT 192,168,0,10,223,46
      Net::FTP=GLOB(0x8244e84)<<< 200 PORT command successful.
      Net::FTP=GLOB(0x8244e84)>>> STOR howllog.html
      Net::FTP=GLOB(0x8244e84)<<< 150 Opening ASCII mode data connection for howllog.html.
      Net::FTP=GLOB(0x8244e84)<<< 226 Transfer complete.
      Net::FTP=GLOB(0x8244e84)>>> QUIT
      Net::FTP=GLOB(0x8244e84)<<< 221 Goodbye.

      So obviously the success of "TYPE binary" has nothing to do with it. It's the PORT command that's killing me. When it failed, it said "invalid number of arguements", and we can clearly see 6 arguements were passed. In this last example there are 6 arguements as well, but the PORT was successful.

      Back to my meditations