Tek-Tips is the largest IT community on the Internet today!

Members share and learn making Tek-Tips Forums the best source of peer-reviewed technical information on the Internet!

  • Congratulations TouchToneTommy on being selected by the Tek-Tips community for having the most helpful posts in the forums last week. Way to Go!

(To me) strange behaviour calling subs

Status
Not open for further replies.

InDenial

Technical User
Aug 1, 2003
191
NL
Hi everyone,

I have this weird behaviour. (maybe it is weird because I am not seeing what I am doing wrong).

I use the Net::Telnet module and I am trying to do some error handling.

The script has the following parts:

1. Connect to the switch
2. Login to the switch
3. Excecute some commands

I declared the $host variable in the beginning. In my understanding this means that the variable (when set) is known to the whole script. right?

I itterate through all the hosts in the @hosts array to do the mentioned parts. What I find strange is that when I call a sub from within the foreach loop I need to provide the $host everytime.

Ok now something goes wrong. I am trying to telnet using the wrong password. As you can see in the login sub I call the Errors sub. I did not provide the $host but the Errors sub knows what $host is.

Another component and something else goed wrong. I am trying to open a telnet connection but the component does not respond. again I call the Errors sub without the $host. This time from within the foreach loop but it gives me an error that it does not know $host.

I do have warnings and strict in the script and it does not give me any other errors.

I might be overlooking something so I hope someone can tell me what I am overlooking.

Code:
my $host;
my @hosts = qw(127.0.0.1 10.0.0.1);

my $t = new Net::Telnet (Timeout => 10, 
                      Prompt => '/\\\\user>/', 
                      Input_log => 'inputlog', 
                      Dump_log => 'dumplog', 
                      cmd_remove_mode => 0, 
                      Errmode => 'return'); 

$t->input_log(\*STDOUT);

foreach $host(@hosts){
	print OUTPUT "----------------Start $host----------\n";
	print OUTPUT "$host : Start Telnet\n";
	$command = "connect";
        if ($t->open("$host")) {
		if (&login($host)){
			&dostuff($host);
		}
	}
	else {[b]&Errors('CONERROR01)[/b]};
		
	print OUTPUT "----------End $host-------\n";
}


########### subs ##########################

sub Errors {
	my $error = $_[0];
	if ($command eq "connect" || $command eq "login"){
		print OUTPUT "$host : $command : $Errorlist{$error}\n";
	}
	else {
		my $lastline = $t->lastline;
		print OUTPUT "$host : $lastline\n";
	}
}

sub login {
	$host = $_[0];
	$command = "login";
	my ($prematch, $match) = $t->waitfor(Match => '/login: $/',
		Errmode => 'return');
	if (!$match) {
		&Errors('LIERROR01');
		return 0;
	}
	print OUTPUT $host." : Login prompt\n";
	$t->print("user");
	($prematch, $match) = $t->waitfor(Match => '/password: $/', 
		Errmode => 'return');
	if (!$match) {
		&Errors('LIERROR02');
		return 0;
	}
	print OUTPUT $host." : password prompt\n";
	$t->print("password");
	($prematch, $match) = $t->waitfor(Match => '/\\\\user>/', 
		Errmode => 'return');
	if (!$match){
		[b]&Errors('LIERROR03');[/b]
		return 0;
	}
	print OUTPUT $host." : Switch prompt\n";
}

InDenial

 
Hmm the line:

else {&Errors('CONERROR01)}; should be

else {&Errors('CONERROR01')};

When setting it to bold I must have accidentaly deleted the '.

InDenial

 
Is this the whole script cause you said you [red]use strict;[/red] and [red]use warnings[/red] but your $command variable is not defined as 'my' or 'our'.

Now you shouldn't use 'my $host' for the whole script, and also use the same name inside your subroutines cause it redifines it. And you might end up having problems.

whats the point then of $host = $_[0]; if the whole script can see the $host, why dont you use it straight into the sub. It is not "that" recomended, but then again perl will not tell you anything if you do so.


``The wise man doesn't give the right answers,
he poses the right questions.''
TIMTOWTDI
 
Thanks for the reply..

The above is the part of my script that matters I think. The script never changes the value of $host as far as I can see. (my knowledge is still somewhat limited).

I used the $host = $_[0]; because somehow that was the only way to get the $host variable into the sub.

The $command variable is also declared as an array in the beginning of the script using:

Code:
my $command = "";
my @commands = ("dir","netstat");

as a result of the above I decided to provide teh subs with the needed information. The script that follows works... but ofcourse I would appreciate some feedback...

Code:
#!/bin/perl -w 

use strict;
use warnings; 

########### Load Modules ######################## 

use Net::Telnet (); 

############ Prepare Variables ################## 
my $host;
my @hosts = qw(10.10.0.1 127.0.0.1);
my %Errorlist = (
	"CMDERROR01" => "The command took longer than the timeout of 10 seconds (Try increasing the timeout)",
	"LIERROR01" => "The script never saw the login prompt",
	"LIERROR02" => "The script never saw the password prompt(Probably error in script)",
	"LIERROR03" => "Wrong Username or Password",
	"CONERROR01" => "Unable to reach the switch through telnet"
);
my $command = "";
my @commands = ("dir","netstat");	

########### Prepare OUTPUT Files ################ 

my $output = 'outputfile';

########### Open OUTPUT Files ################ 

open (OUTPUT, ">$output") || die "can not open $output\n"; 

########### Telnet ############# 

my $t = new Net::Telnet (Timeout => 10, 
                      Prompt => '/\\\\user>/', 
                      Input_log => 'inputlog', 
                      Dump_log => 'dumplog', 
                      cmd_remove_mode => 0, 
                      Errmode => 'return'); 

$t->input_log(\*STDOUT);

foreach $host(@hosts){
	$command = "connect";
	print OUTPUT "Start $host-------------------\n";
	print OUTPUT "$host : $command : Start Telnet\n";
	if ($t->open("$host")) {
		print "Connected to : $host\n";
		$command = "login";
		if (&login($host,$command)){
			print "Logged In to : $host\n";
			&dostuff($host);
		}
	}
	else { 
		&Errors($host,$command,'CONERROR01')};
	
	print OUTPUT "End $host--------------------\n";
}

########### Close Output files ############

close OUTPUT;

########### subs ##########################

sub Errors {
	my ($a,$b,$c) = @_;
	print OUTPUT "$a : $b : $Errorlist{$c} ($c)\n";
}


sub login {
	my ($a,$b) = @_;
	my ($prematch, $match) = $t->waitfor(Match => '/login: $/',
		Errmode => 'return');
	if (!$match) {
		&Errors($a,$b,'LIERROR01');
		return 0;
	}
	print OUTPUT "$a : $b : Login prompt\n";
	$t->print("user");
	($prematch, $match) = $t->waitfor(Match => '/password: $/', 
		Errmode => 'return');
	if (!$match) {
		&Errors($a,$b,'LIERROR02');
		return 0;
	}
	print OUTPUT "$a : $b : password prompt\n";
	$t->print("password");
	($prematch, $match) = $t->waitfor(Match => '/\\\\user>/', 
		Errmode => 'return');
	if (!$match){
		&Errors($a,$b,'LIERROR03');
		return 0;
	}
	print OUTPUT "$a : $b : Switch prompt\n";
}

sub dostuff {
	my $a = $_[0];
	foreach $command (@commands){
		if($t->cmd(String => $command, Errmode => 'return')){
			print OUTPUT "$a : $command : \n";
		}
		else {
			&Errors($a,$command,'CMDERROR01');
			return 0;
		}
	}
}

InDenial

 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top