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

Oh most high holy ones, I am back for another lesson.

I need to FTP two files from my web server to a remote server periodically as I explained here: http://perlmonks.org/?node_id=702448

The problem I'm having is that execution from an shtml page times out occasionally which interrupts the process. Since I'm tranfering two files, I decided to see if I can shorten the execution time by doing the transfer in parallel rather than sequentially. I have written the following script to try to accomplish this:

#!/usr/bin/perl if (fork) { use Net::FTP; $ftp = Net::FTP->new("ftp.remoteserver.com", Passive => 1, Timeout + => 300, Debug => 0) or die "Cannot contact $host: $!"; $ftp->login("user1",'password1'); $ftp->binary(); $ftp->put("/home/users/web/blah/directory/file1"); $ftp->quit; } else { $ftp = Net::FTP->new("ftp.remoteserver.com", Passive => 1, Timeout + => 300, Debug => 0) or die "Cannot contact $host: $!"; $ftp->login("user2",'password2'); $ftp->binary(); $ftp->put("/home/users/web/blah/directory/file2"); $ftp->quit; } print "Content-type: text/html\n\n"; print <<"EOF"; <font face="arial" color=red> Transfer Complete! </font> EOF exit;
The script seems to save about 50% of the execution time. And early indications are that this script seems to have solved my problem. My previous script had the two transfers in sequence.

Since I'm very new to Perl scripting, after you have a look please answer the following simple questions for me:

- Does the script actually produce parallel transfer?
- Can you suggest any improvement?
Curiously, the script sends "Transfer Complete! Content-type: text/html Transfer Complete!" to my web page after completion, however, I believe I now understand why this is true. Thanks as always for your advice.

Replies are listed 'Best First'.
Re: Shortening Execution Time
by JavaFan (Canon) on Aug 09, 2008 at 21:13 UTC
    Assuming the fork doesn't fail, you do get transfers in parallel. However, both the parent and the child will print the content type and the Transfer Complete message.

    You may want to exit() in the child, and wait() in the parent. And you may want to check whether the transfer actually succeeded, currently you print Transfer Complete, regardless whether it actually succeeded or not.

      Unix (flavours; don't know what Windows does): Additionally, you might want to catch or ignore the SIGCHLD-signal that the parent process receives when the child process dies. If there is only one child process, a $SIG{CHLD} = sub { wait(); }; as described in perlipc can be used as a starter. This should protect the parent process in case the child process dies while the parent process has not yet reached wait() (race situation).
      Update: Well, after some testing, this seems to be an issue with older versions of perl and OS. The default SIGCHLD-handler of Perl 5.8.8 (Linux) works fine. Anyway, the SIG-handler might be useful if you are interested in an asynchronous notification of a child's decease.
Re: Shortening Execution Time
by GrandFather (Saint) on Aug 09, 2008 at 23:34 UTC

    use is evaluated before your code is executed so the single use inside an if block is effectively global to everything. It is better to put use statements at the top of your script where they can easily been seen and their visibility is a better match to their scope. If you want to optionally "use" a module, use require instead.

    $host is not initialised before it is used in the die statements. Using strictures would detect the problem the first time you tried to run the code. Tip: always use strictures (use strict; use warnings; - see The strictures, according to Seuss).


    Perl reduces RSI - it saves typing
Re: Shortening Execution Time
by DrWho_100 (Acolyte) on Aug 11, 2008 at 14:08 UTC
    Thanks for your suggestions - this is a great way to learn!!! (I especially enjoyed Dr. Seuss on use strict and warnings.) I've incorporated some of your suggestions into my code and am now certain that it's working the way I intended. Bottom line: it has succeeded in shortening the execution time to solve my problem.