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

I am using Net::FTP to transfer MP3 files from Linux to a Windows environment. It works almost perfect. However, I have two functions below, one for sending a file from Linux->Windows, and one for deleting the uploaded file. I am using a CGI::App framework and outputting with HTML::Template.
If I upload a file, check if it exists, delete the file, check if it's gone, when I upload the file again I got a timeout error from the Net::FTP->new().
I need to find out what's wrong, so I put the call to Net::FTP in Debug mode. Does anyone know what's causing the problem? or does anyone know how to print out the debugging information to an HTML::Template file?
sub sendFile { # application object my $self = shift; # load template files my $tmpl = $self->param('info' => $self->load_tmpl ('info.phtml')); # create an ftp object my $ftp = Net::FTP->new("XXX.XX.XX.XXX", Debug => 1, Port => 21) or di +e "Cannot connect to host: $@"; # login to the ftp server $ftp->login("user",'pass') or die $ftp->message; # get root directory $ftp->cwd() or die $ftp->message; # get the filename my $filename = "dir+filename"; # check if file exist if(-e $filename){ # send file in binary mode $ftp->binary; # send a file to the remote server $ftp->put($filename) or die $ftp->message; } # quit the ftp connection $ftp->quit; # output return $tmpl->output; } sub deleteFile { # application object my $self = shift; # load template files my $tmpl = $self->param('info' => $self->load_tmpl ('info.phtml')); # create an ftp object my $ftp = Net::FTP->new("XXX.XX.XX.XXX", Debug => 1, Port => 21) or di +e "Cannot connect to host: $@"; # login to the ftp server $ftp->login("user",'pass') or die $ftp->message; # get root directory $ftp->cwd() or die $ftp->message; # get the filename my $filename = "filename"; # delete a file to the remote server $ftp->delete($filename); # quit the ftp connection $ftp->quit; # output return $tmpl->output; }

Replies are listed 'Best First'.
Re: Print debug information from Net::FTP
by bowei_99 (Friar) on Apr 01, 2006 at 21:44 UTC
    Your error
    Error executing run mode 'send_file': Cannot connect to host: Net::FTP +: connect: timeout at /home/domains/xxx/www.xxx.com/aa/system/modules +//FTP.pm line 16. at /home/domains/xxx/www.xxx.com/aa/index.cgi line +20
    as well as the fact that it's happening 3/4 times makes me think that there's some sort of network connectivity issues. To isolate and confirm this,
    • Run the command netstat -i from the linux box. (You can also run is netstat -aen on Windows 2k/XP/2k3). Does it give any errors? If so, it would be a problem not related to your code, e.g. bad network card, problem with the switch, etc.

    • Try highering the timeout value - the default is 120, like so -

      use Carp; .... my $ftp = Net::FTP->new("XXX.XX.XX.XXX", Debug => 1, Port => 21, => Ti +meout => 300) or croak "Cannot connect to host: $@";
      Note that I used croak instead of die, which will give you more verbose information.

    • You could also loop a couple times until you get a connection:

      my $ftp = Net::FTP->new("XXX.XX.XX.XXX", Debug => 1, Port => 21, => Ti +meout => 300); my $num_tries = 0; my $max_tries = 5 #you decide how many times you want to try while ( !$ftp) { if ($num_tries< $max_tries) ) { ++$num_tries; $ftp = Net::FTP->new("XXX.XX.XX.XXX", Debug => 1, Port => 21, + => Timeout => 300); } if ($num_tries >= $max_tries) ) { croak "Cannot connect to host, failed after $num_tries times +: $@"; } }
    • When it fails to connect, you could write code using Net::Ping to make sure it's up.

    -- Burvil

      After running netstat -i
      ssh prompt: netstat -i Kernel Interface table Iface MTU Met RX-OK RX-ERR RX-DRP RX-OVR TX-OK TX-ERR TX-DRP TX- +OVR Flg Warning: cannot open /proc/net/dev (Permission denied). Limited output +. missing interface information: Permission denied
      I tried to higher to timeout value but it will still timeout. If it doesn't work right away, it's not going to work. However, I am calling these subroutines from links in a html page. If I click a link an nothing happens within approx. 2 seconds, I click it again and again. eventually it will work. It might be on the second, third or ninth try..., but it will finally connect

      No luck with the loop either, same problem.

      While waiting for the timeout error, I used ping on the windows server with the following result:

      148 packets transmitted, 148 packets received, 0% packet loss round-trip min/avg/max = 0.2/0.2/0.3 ms
Re: Print debug information from Net::FTP
by bowei_99 (Friar) on Apr 01, 2006 at 18:42 UTC
    First, for clarity, you want to indent the code within each subroutine, e.g.
    sub sendFile { # application object my $self = shift; # load template files my $tmpl = $self->param('info' => $self->load_tmpl('info.phtml') +); ... }
    Re: your question of where the bug is, I think it's here:
    # get the filename my $filename = "dir+filename"; # check if file exist if(-e $filename){
    1. Is the actual path of the file you want to send really "dir+filename"? Or was that intended to be a note to yourself to assign it something like "/home/boboson/media/mp3.mp3"?
    2. You may want to replace your -e $filename test with -f $filename, as the former tests only for existence, the latter tests if it's an actual plain file. See the perldoc for more info and other tests you can run.

    -- Burvil

      dir+filename is not my actual code, I just didn't wan't to display the complete path.
      The code works, but not all of the time. It works approx. 3 out of 4 times.
      Thanks for the -f tip!
        What's the specific timeout message you're getting? Also, have you tried setting the debug level to something higher? According to the Net::Cmd docs (since Net::FTP inherits from Net::Cmd), the debug level may be set to more than 1, and different packages give different response.

        Update: You might also try using a network sniffer (if that's allowed on your network) to see what's actually being passed between your Linux and Windows box. Ethereal comes installed on a lot of linux distros, and has a pretty nice GUI, or, if you prefer the command line, you can use tcpdump.

        -- Burvil