loops in perl automated ftp

B

banzai

Need help with the following automated ftp script please;

if (defined ($ftp1)) {
$ftp1->login($FTP1user,$FTP1password) or LogError("FTP login to
$FTP1server failed");
if (defined $FTP1destination){
$ftp1->cwd($FTP1destination) or LogError("Could not change directory
to $FTP1destination on $FTP1server");
}
$ftp1->binary;
$ftp1->put("$FileBodyName.tar.gz") or LogError("Could not FTP copy
$FileBodyName.tar.gz to $FTP1server");
$ftp1->put("$DataTagName.gz") or LogError("Could not FTP copy
$DataTagName.gz to $FTP1server");
$ftp1->quit;
} else {
LogError("FTP open failed to $FTP1server, error code: $!");
}
#



I need to modify the above so that the ftp transfers (put's) are attempted
up to 5 times in case the remote server does not respond. No time delay
needed between retries.

TIA
 
S

Snorik

Need help with the following automated ftp script please;

if (defined ($ftp1)) {
$ftp1->login($FTP1user,$FTP1password) or LogError("FTP login to
$FTP1server failed");
if (defined $FTP1destination){
$ftp1->cwd($FTP1destination) or LogError("Could not change directory
to $FTP1destination on $FTP1server");
}
$ftp1->binary;
$ftp1->put("$FileBodyName.tar.gz") or LogError("Could not FTP copy
$FileBodyName.tar.gz to $FTP1server");
$ftp1->put("$DataTagName.gz") or LogError("Could not FTP copy
$DataTagName.gz to $FTP1server");
$ftp1->quit;} else {

LogError("FTP open failed to $FTP1server, error code: $!");}

#

I need to modify the above so that the ftp transfers (put's) are attempted
up to 5 times in case the remote server does not respond. No time delay
needed between retries.

TIA

Why not simply use a counter variable in a while loop?

my $count = 0;
while ($count <= 4)
{
$ftp1->put("$FileBodyName.tar.gz") or LogError("Could not FTP
copy $FileBodyName.tar.gz to $FTP1server");
$ftp1->put("$DataTagName.gz") or LogError("Could not FTP copy
$DataTagName.gz to $FTP1server");
$count++;
}

?
 
T

Tad J McClellan

["Followup-To:" header set to comp.lang.perl.misc.]

Snorik said:
Why not simply use a counter variable in a while loop?


Because if the remote server _does_ respond, it will upload the
same file 5 times when once was enough.

The solution must somewhere include a test of whether the server
responded or not.

my $count = 0;
while ($count <= 4)

That is an error-prone way to do it.

foreach my $count ( 0 .. 4 )
or
foreach my $count ( 1 .. 5 )

is much easier to read (and therefore, easier to get right).
 
T

Ted Zlatanov

b> $ftp1->put("$FileBodyName.tar.gz") or LogError("Could not FTP copy $FileBodyName.tar.gz to $FTP1server");
b> $ftp1->put("$DataTagName.gz") or LogError("Could not FTP copy $DataTagName.gz to $FTP1server");

b> I need to modify the above so that the ftp transfers (put's) are attempted
b> up to 5 times in case the remote server does not respond. No time delay
b> needed between retries.

Each one can be done like so (untested code):

for (1..5)
{
last if $ftp1->put("$FileBodyName.tar.gz");
LogError("Could not FTP copy $FileBodyName.tar.gz to $FTP1server");
}

In other words, do the loop 5 times unless one of the put() calls
succeeds. If that happens, exit early with `last'.

Ted
 
B

banzai

Ted Zlatanov said:
b> $ftp1->put("$FileBodyName.tar.gz") or LogError("Could not FTP copy
$FileBodyName.tar.gz to $FTP1server");
b> $ftp1->put("$DataTagName.gz") or LogError("Could not FTP copy
$DataTagName.gz to $FTP1server");

b> I need to modify the above so that the ftp transfers (put's) are
attempted
b> up to 5 times in case the remote server does not respond. No time delay
b> needed between retries.

Each one can be done like so (untested code):

for (1..5)
{
last if $ftp1->put("$FileBodyName.tar.gz");
LogError("Could not FTP copy $FileBodyName.tar.gz to $FTP1server");
}

In other words, do the loop 5 times unless one of the put() calls
succeeds. If that happens, exit early with `last'.

Ted


Thanks Ted - looks like a good solution so I will try.
Snorik, this one suits best I think as your solution ignored exit status (if
thats the right word in perl) of previous attempt(s) . i.e. if first attempt
succeeds then no need to retry
 
B

banzai

Ted Zlatanov said:
b> $ftp1->put("$FileBodyName.tar.gz") or LogError("Could not FTP copy
$FileBodyName.tar.gz to $FTP1server");
b> $ftp1->put("$DataTagName.gz") or LogError("Could not FTP copy
$DataTagName.gz to $FTP1server");

b> I need to modify the above so that the ftp transfers (put's) are
attempted
b> up to 5 times in case the remote server does not respond. No time delay
b> needed between retries.

Each one can be done like so (untested code):

for (1..5)
{
last if $ftp1->put("$FileBodyName.tar.gz");
LogError("Could not FTP copy $FileBodyName.tar.gz to $FTP1server");
}

In other words, do the loop 5 times unless one of the put() calls
succeeds. If that happens, exit early with `last'.

Ted


Actually, one more question :)

Could a smiliar 5x loop be put around the whole ftp sequence i.e. login, cwd
and put so tha the whole process is repeated 5 times if required (not just
the put) and exit early if the put succeeds
 
S

Snorik

Thanks Ted - looks like a good solution so I will try.
Snorik, this one suits best I think as your solution ignored exit status (if
thats the right word in perl) of previous attempt(s) . i.e. if first attempt
succeeds then no need to retry

Yes, this is completely right, I forgot about that actually :) Teds
solution is shorter, without being illegible.
 
J

J. Gleixner

banzai said:
Actually, one more question :)

Could a smiliar 5x loop be put around the whole ftp sequence i.e. login, cwd
and put so tha the whole process is repeated 5 times if required (not just
the put) and exit early if the put succeeds

Sure. Why do you think it wouldn't work? Actually, maybe it'd
be better to figure out why it's failing to work the first time.

You'll have to exit out of the loop correctly, probably easiest to
use a label.

perldoc -f last
 
S

Snorik

["Followup-To:" header set to comp.lang.perl.misc.]



Snorik said:
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Why not simply use a counter variable in a while loop?

Because if the remote server _does_ respond, it will upload the
same file 5 times when once was enough.

The solution must somewhere include a test of whether the server
responded or not.

You are right, as said elsethread, I did not think of that at all.
That is an error-prone way to do it.

foreach my $count ( 0 .. 4 )
or
foreach my $count ( 1 .. 5 )

is much easier to read (and therefore, easier to get right).

Yes, indeed, thanks for pointing that out, I had completely forgotten
about this possibility.
 
T

Ted Zlatanov

b> $ftp1->put("$FileBodyName.tar.gz") or LogError("Could not FTP copy $FileBodyName.tar.gz to $FTP1server");
b> $ftp1->put("$DataTagName.gz") or LogError("Could not FTP copy $DataTagName.gz to $FTP1server");b> I need to modify the above so that the ftp transfers (put's) are attempted
b> up to 5 times in case the remote server does not respond. No time delay
b> needed between retries.
b> Could a smiliar 5x loop be put around the whole ftp sequence i.e. login, cwd
b> and put so tha the whole process is repeated 5 times if required (not just
b> the put) and exit early if the put succeeds

Yes, but then you won't know what failed, and you don't want to do the
first put 5 times if the second one failed 5 times.

You probably want to avoid repeating the loop all over your code, which
is good. I hate repetition too. Perl lets you create anonymous
subroutines, which are basically a block of executable code you can pass
as a variable. With those, you can do:

# untested: try N times to run CODE, and do ERR every time it fails
sub tryN
{
my $N = shift @_;
my $code = shift @_;
my $err = shift @_;

for (1..$N)
{
last if $code->();
$err->();
}
}

# now your program is a bunch of these statements
tryN(5,
sub { $ftp1->put("$FileBodyName.tar.gz") },
sub { LogError("Could not FTP copy $FileBodyName.tar.gz to $FTP1server"); });

There are some scoping rules at play, but nothing you need to worry
about with a simple program. You should probably comment this carefully
if it's going to be used and maintained.


S> Teds solution is shorter, without being illegible.

I really tried to balance between legible and concise, so I'm glad you
liked it.

Thanks
Ted
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,776
Messages
2,569,603
Members
45,190
Latest member
ClayE7480

Latest Threads

Top