Beefy Boxes and Bandwidth Generously Provided by pair Networks
Don't ask to ask, just ask
 
PerlMonks  

Net::FTP troubles

by RedDog (Pilgrim)
on Nov 09, 2001 at 01:55 UTC ( [id://124206]=perlquestion: print w/replies, xml ) Need Help??

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

I am using the Net::FTP module on ActiveState Perl 5.6, build 626, running on Windows NT4 Workstation. I am attempting to put a file out on several of my company's servers, and am having a few troubles. Here is the code I am using at the moment.
#!perl -w use strict; use Net::FTP; my $Local="C:\\Winnt\\Profiles\\jlewis\\desktop"; my $File="cron.file"; my $key; my $IP; my $user="username"; # NOT the real username my $pass="password"; # And DEFINITELY NOT # the real password my %Servers=("1"=>'128.37.37.201', "2"=>'128.38.38.201', "3"=>'128.39.39.201'); chdir($Local); foreach $key(%Servers){ $IP="$Server{$key}"; chomp($IP); my $FTP=Net::FTP->new("$IP"); $FTP->login("$user","$pass"); $FTP->ascii(); $FTP->put($File); $FTP->quit; }
I am getting the following errors when I run this:
Use of uninitialized value in string at line 20,cronftp.pl Can't call method login on an undefined value at line 23,cronftp.pl
I know that this means the error that is causing it all is when I declare the variable $IP to be equal to the value of whatever hash key its currently looping through, but for the life of me, I can't figure out why its uninitialized.
Please just point me in the right direction, and I'll take it from there. Thanks

RedDog

Replies are listed 'Best First'.
Re: Net::FTP troubles
by runrig (Abbot) on Nov 09, 2001 at 02:13 UTC
    foreach $key(%Servers){ should be:
    foreach $key (keys %Servers){
    and actually I'd scrap the first declaration of $key and make that:
    foreach my $key (keys %Servers){
    You'd also do well to check the status of your Net::FTP methods. new() returns undef and an error message in $@ on failure, and the rest will return undef but the error message will be returned from
    $FTP->message (and don't put it in quotes since its a method not a variable).
    And why are you chomping $IP?? It doesn't come from any file or user input...

    Update: Though a good catch, this line:

    $IP="$Server{$key}";
    is almost certainly just a typo here since use strict should be complaining about it (generating a "Global symbol requires explicit package name..." error) before the runtime error that RedDog is currently getting (at least I get a compile time error with build 628, if you don't get one with that code, maybe you should upgrade). And I agree with the opinions that if you don't need a hash, don't put the IP's in a hash.

      I agree about the foreach loop.

      In addition, the actual error message (apparently) refers to the variable $IP as being undefined; this is because the assignment to $IP is using a different hash than the one that is being looped through. The loop starts with:

      foreach $key(%Servers){

      which loops through all of the key/value pairs of the hash %Servers in pseudo-random order (probably not what you wanted, as runrig has said). However, your assignment to $IP uses the variable $key to retrieve values from another hash called %Server, which is undoubtably empty, in fact making $IP undefined.

      Also, as has been noted elsewhere, you most certainly do not need the double quotes around scalar values, for example, $Server{$key}: they force unnecessary interpolation, since $Server{$key} itself is already a string.

      There is no particular reason to use a hash at all, preferring an array, which will preserve your ordering of IP addresses. I would go one step further and remove the unnecessary call to chomp (since the addresses do not end in newlines):

      my @Servers = qw( 128.37.37.201 128.38.38.201 128.39.39.201 ); foreach my $IP ( @Servers ) { my $FTP = Net::FTP->new($IP); if ( $FTP->login($user,$pass) ) { $FTP->ascii(); $FTP->put($File); $FTP->quit; } else { print "Error logging in to $IP: ". $FTP->message ."\n"; } }

      dmm

      
      You can give a man a fish and feed him for a day ...
      Or, you can teach him to fish and feed him for a lifetime
      
        I suspect the %Server vs. %Servers thing was a typo. His code sample shows him using strict, so an error like this should have been caught early on.

        Good catch, though. I'd missed this one.

Re: Net::FTP troubles
by Fastolfe (Vicar) on Nov 09, 2001 at 03:31 UTC
    What is the purpose of $key and the key to your hashes? Remember that pulling out the keys or hashes as they are won't result in sorted output, so you're going to be connecting to each FTP server in a pseudo-random order. It might be more efficient to just stick these IP's into an array and iterate through the array.
    use strict; use Net::FTP; my $Local = 'c:\winnt\profiles\jlewis\desktop'; my $File = "cron.file"; my ($user, $pass) = ("username", "password"); my @servers = qw/ 128.37.37.201 128.38.38.201 128.39.39.201 /; chdir($Local) or die "$Local: $!"; foreach (@servers) { my $FTP = new Net::FTP ($_) or die "Can't connect to $_"; $FTP->login($user, $pass) or die "Can't login as $user" $FTP->ascii; $FTP->put($File) or die "Can't put $File" $FTP->quit; }
    As another poster mentioned, you were iterating through %Servers as a whole, which means you were trying to make connections to "1", "128.37.37.201", "2", etc. Since the first one wasn't a valid IP/hostname, the creation of your $FTP object failed (which you weren't checking for), which means your call to $FTP->login() couldn't be done since $FTP wasn't defined. Hence all of those messages.

    The warning about the uninitialized value came about because you were doing this: $IP="$Server{$key}" Since $key at one point was "128.37.37.201", you were trying stuff the value of that key in the hash into $IP. Since there was no key by that name (it was a value, remember), the result was undefined, hence that warning.

    Hope this helps..

Re: Net::FTP troubles
by davis (Vicar) on Nov 09, 2001 at 15:13 UTC
    Quick comment: in your code you've got the line:
    $IP="$Server{$key}";
    This can (and probably should) be:
    $IP=$server{$key};
    Quotes tell perl to create a string - but the value in the server hash is already a string, so they're unnecessary. Read
    perldoc -q quoting
    for more info.
Re: Net::FTP troubles
by blahblahblah (Priest) on Nov 09, 2001 at 11:46 UTC
    You've defined %Servers (plural), but you're looking for the IP in %Server (singular). I think that plus the -w are what's causing the error message.
Re: Net::FTP troubles
by alien_life_form (Pilgrim) on Nov 09, 2001 at 20:40 UTC
    Greetings,

    to the many nuggets of wisdom in the thread, let me add the almost cliche:

    use strict;
    which would have caught at least one of the snafus (%Server/%Servers).

    Update

    And so it came to pass that alien_life_form (the dunce) di forego to Use the Source and missed a use strict that was plainly under his nose.... Duh!
    It appears so obvious that strict should complain about the %Server %Servers affair... so why doesn't it?
    Cheers,
    alf
    You can't have everything: where would you put it?
Re: Net::FTP troubles
by RedDog (Pilgrim) on Nov 10, 2001 at 00:47 UTC
    After reading the first reply from runrig, I promptly found the nearest wall and started banging my head against it. Thank you all for pointing out (IMHO) my boneheaded mistake. And, yes, the %Servers vs %Server was just a typo. I had printed the program out and had to type it in (my workstation doesn't have internet access, so I am typing this from a dialup connection). I fixed my mistake, and the script ran just fine. I will take all of your comments though, and revise the script to make it a little more neater. Thanks again.

    RedDog
Re: Net::FTP troubles
by Anonymous Monk on Nov 10, 2001 at 16:40 UTC
    No, your initialization of $FTP is failing. Never used Net::FTP, but maybe it's not connecting to the server. Is the server on an odd port that you didn't specify?
Re: Net::FTP troubles
by Anonymous Monk on Nov 12, 2001 at 22:56 UTC
    Instead of: foreach $key(%Servers){ It should be: foreach $key(keys %Servers){

Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: perlquestion [id://124206]
Approved by root
help
Chatterbox?
and the web crawler heard nothing...

How do I use this?Last hourOther CB clients
Other Users?
Others meditating upon the Monastery: (8)
As of 2024-04-25 11:32 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found