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

Hi All,

Another one that I cant quite get my head around :-(

I have this hash

my $router_data = [ { routerName => 'asr01', ipAddr => '1.1.1.1', }, { routerName => 'asr02', ipAddr => '2.2.2.2', }, ];
And this is the code:
for my $router ( @$router_data ) { my $tty; ### Create SSH Session print "\n" . "Logging into $router->{routerName}..." . " \n"; my $ssh = Net::SSH::Expect->new ( host => $router->{routerName}, password=> $pWord, user => $uName, timeout => '3', raw_pty => 1 ); ### Logon to the Router $tty = $ssh->login(); if($tty !~ /$router->{routerName}/) { die "Error: no prompt received.\n\n"; } if ( $Action eq 'status' ) { checkStatus($router->{routerName}); } sub checkStatus { my $routerName = $_[0]; my $test; if ($routerName eq 'asr01') { $test = $ssh->exec("show run | in hostname "); } else { $test = $ssh->exec("show clock"); } print $test; } }

For love nor money I cannot get the code to execute commands on asr02

Here the output I get

$ ./test.pl status Logging into asr01... show run | in hostname hostname asr01 asr01# Logging into asr02... show clock 16:48:30.421 UTC Thu Jul 4 2013 asr01#

As you can see it seems to be running both commands on asr01, I know it is logging into asr02 as the logs see a Login connection

All help appreciated.

Thanks

Nick

Replies are listed 'Best First'.
Re: For loop and Sub Routines
by NetWallah (Canon) on Jul 04, 2013 at 17:07 UTC
    The problem is with the embedded "sub checkStatus".

    It uses the global "$ssh", which gets nailed in at compile-time. (Using the term 'Compile-time' loosely).

    I suggest taking the sub declaration outside the "for" loop, then passing in $ssh.

    Update:Here is an illustration of the issue:

    >perl -E 'for (1..2){say "In loop $_"; my $z=$_+20; x($_); sub x{my $y +=$_[0]; say "In Sub. Param= $y. z=$z"}}' In loop 1 In Sub. Param= 1. z=21 In loop 2 In Sub. Param= 2. z=21
    When the parameter is "2", then $z should be 22. This would be the case if $z were passed-in.

                 My goal ... to kill off the slow brain cells that are holding me back from synergizing my knowledge of vertically integrated mobile platforms in local cloud-based content management system datafication.

      Thanks for the quick reply...

      As I am a bit of a newbie to this, are you suggesting.

      I am on the train home so cant test this for sure...

      for my $router ( @$router_data ) { my $tty; ### Create SSH Session print "\n" . "Logging into $router->{routerName}..." . " \n"; my $ssh = Net::SSH::Expect->new ( host => $router->{routerName}, password=> $pWord, user => $uName, timeout => '3', raw_pty => 1 ); ### Logon to the Router $tty = $ssh->login(); if($tty !~ /$router->{routerName}/) { die "Error: no prompt received.\n\n"; } if ( $Action eq 'status' ) { checkStatus($router->{routerName,$ssh}); } } sub checkStatus { my $routerName = $_[0]; my $ssh = $_[1]; my $test; if ($routerName eq 'asr01') { $test = $ssh->exec("show run | in hostname "); } else { $test = $ssh->exec("show clock"); } print $test; }
        The call should read:
        checkStatus($router->{routerName}, $ssh);
        ALso, it is more common (and lazier, and more idiomatic) to code the passed parameters this way:
        sub checkStatus { my ($routerName, $ssh) = @_; ...
        This allows you to add parameters easily, and makes parameter positions visually identifiable without having to examine indexes.

                     My goal ... to kill off the slow brain cells that are holding me back from synergizing my knowledge of vertically integrated mobile platforms in local cloud-based content management system datafication.

Re: For loop and Sub Routines
by shawnhcorey (Friar) on Jul 04, 2013 at 17:07 UTC

    This part of your code says to only to `show run` if it's "asr01". IF you want it to run for everything, take out the if statement.

    if ($routerName eq 'asr01') { $test = $ssh->exec("show run | in hostname ");