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

My problem is simple im sure, the thing is that i cant see it :o)

I have a script that takes 5 arguments:
"filelist hostlist username password directory"

It starts a ftp session to the first node in the hostlist and transfers all the files from the filelist.

This works fine as long as i only have one node in the nodelist.. if i have more it just goes:

$ ./ftpbackup.pl filelist.txt hostlist.txt <username> <password> /remote/directory
Connecting to host1.com
Getting file1
Getting file2
Connecting to host2.com

And nothing more one reson can be that i just started learning perl last week.. ;o)

Thanks!
Tommy Rohde - yxol@fetburk.nu

#!/usr/bin/perl -w # # Comments are allowed in both the file and host list if # the comment row begins with a '#' sign. # Entries in the file and host list should be seperated with # a new row. spaces or other signs will make the script fail. # use Net::FTP; use strict; my $usage = "$0 filelist hostlist username password directory\n"; my $filelist = $ARGV[0] or die "$usage"; my $hostlist = $ARGV[1] or die "$usage"; my $username = $ARGV[2] or die "$usage"; my $password = $ARGV[3] or die "$usage"; my $home = $ARGV[4] or die "$usage"; my $debug = 5; my $backupnode = undef; open(FilesToGet, $filelist) or die "can't open filelist $filelist: $!\n"; open(HostsToGet, $hostlist) or die "can't open hostlist $hostlist: $!\n"; HOSTLOOP: while (<HostsToGet>) { next HOSTLOOP if /#/; print STDERR "Connecting to $_" if $debug > 3; chomp; $backupnode = $_; FILELOOP: while (<FilesToGet>) { next FILELOOP if /#/; my $ftp = Net::FTP->new($backupnode); $ftp->login($username, $password); $ftp->cwd($home); print STDERR "Getting $_" if $debug > 3; chomp; $ftp->get($_,"$backupnode." . $_); $ftp->quit; } }

Edit kudra, 2001-11-07 Changed title

Replies are listed 'Best First'.
Re: This should work.. i think
by claree0 (Hermit) on Nov 07, 2001 at 14:37 UTC
    You've iterated through your 'files to get' in the first loop with node 1 - no files to retrieve for subsequent nodes. You need to reset to file pointer on your file list (or read it into an array to start with and iterate through that array for each node).
Re: This should work.. i think
by suaveant (Parson) on Nov 07, 2001 at 19:26 UTC
    Yeah, if you put your file list in an array like so:
    #!/usr/bin/perl -w # # Comments are allowed in both the file and host list if # the comment row begins with a '#' sign. # Entries in the file and host list should be seperated with # a new row. spaces or other signs will make the script fail. # use Net::FTP; use strict; my $usage = "$0 filelist hostlist username password directory\n"; my $filelist = $ARGV[0] or die "$usage"; my $hostlist = $ARGV[1] or die "$usage"; my $username = $ARGV[2] or die "$usage"; my $password = $ARGV[3] or die "$usage"; my $home = $ARGV[4] or die "$usage"; my $debug = 5; my $backupnode = undef; open(FilesToGet, $filelist) or die "can't open filelist $filelist: $!\n"; my @FilesToGet = <FilesToGet>; close FilesToGet; open(HostsToGet, $hostlist) or die "can't open hostlist $hostlist: $!\n"; while (<HostsToGet>) { next if /#/; print STDERR "Connecting to $_" if $debug > 3; chomp; $backupnode = $_; for(@FilesToGet) { next if /#/; my $ftp = Net::FTP->new($backupnode); $ftp->login($username, $password); $ftp->cwd($home); print STDERR "Getting $_" if $debug > 3; chomp; $ftp->get($_,"$backupnode." . $_); $ftp->quit; } }
    it should be happier. Although you may want to add some code to make it skip files you grabbed... actually, $_ = '#'; at the bottom of the for loop would do that :)

                    - Ant
                    - Some of my best work - (1 2 3)

      Thanks mate.. but its already fixed and i almost did it all by myself *proud*

      #!/usr/bin/perl # # Entries in the file and host list should be seperated with # a new row. spaces or other signs will make the script fail. # You can use comments if you put a '#' sign in front of the # line, but it will make the printout of number of # hosts/files that are beeing backuped to show the wrong numbers. # use Net::FTP; use strict; my $usage = "$0 filelist hostlist username password directory\n"; my $filelist = $ARGV[0] or die "$usage"; my $hostlist = $ARGV[1] or die "$usage"; my $username = $ARGV[2] or die "$usage"; my $password = $ARGV[3] or die "$usage"; my $home = $ARGV[4] or die "$usage"; my $debug = 5; my @hostarr; my @filearr; my $nr = 0; open(FilesToGet, $filelist) or die "can't open filelist $filelist: $!\n"; open(HostsToGet, $hostlist) or die "can't open hostlist $hostlist: $!\n"; @hostarr = <HostsToGet>; chomp @hostarr; my $hostarrnr = @hostarr; @filearr = <FilesToGet>; chomp @filearr; my $filearrnr = @filearr; print "\nHosts: $hostarrnr\n"; print "Files: " . ($filearrnr * $hostarrnr) . "\n"; print "\n"; for (my $nr1 = 0; $nr1 < $hostarrnr; $nr1++) { next if ($hostarr[$nr1] =~ /^#/ | undef); print STDERR "Connecting to $hostarr[$nr1]\n" if $debug > 3; my $ftp = Net::FTP->new($hostarr[$nr1]); $ftp->login($username, $password); $ftp->cwd($home); for (my $nr2 = 0; $nr2 < $filearrnr; $nr2++) { next if ($filearr[$nr2] =~ /^#/ | undef); print STDERR "Getting $filearr[$nr2]\n" if $debug > 3; $ftp->get($filearr[$nr2],("$hostarr[$nr1]." . $filearr[$nr2])) +; } $ftp->quit; }
Re: This should work.. i think
by impossiblerobot (Deacon) on Nov 07, 2001 at 23:47 UTC
    You could add a:

    seek(FilesToGet, 0, 0);

    before your FILELOOP: label to reset the filehandle position to the top of the file.

    However, the array solution would be more efficient (as long as the list of files isn't too long to fit in memory), since you're not having to read the same information from the file over and over.

    Impossible Robot