in reply to Re^3: Problem with Net::SSH::Expect on unavailable hosts
in thread Problem with Net::SSH::Expect on unavailable hosts

First I'd like to thank all of you who are commenting...

Second, I wanted to reiterate that the return value from the run_ssh ($login_output) always returns the value 1, no matter of it was successful or not. From what I read in the docs, this is because the return value of the spawn is returned, meaning that the ssh process was spawned successfully. The issue lies in the fact that the ssh connection dies immediately afterward (connection refused)... so the question becomes, how can I detect that an ssh connection has been terminated?

It appears that is the reason for this line:
($ssh->read_all(2) =~ />\s*\z/) or die "where's the remote prompt?"
But the script dies before it even finishes processing that line. The attempt to call a method on the $ssh object is what aborts the script. After the $ssh->run_ssh();, *anything* that is called from $ssh will do the same thing.

I've tried using login() with a password instead, but according to the docs, login() actually calls run_ssh() anyway, so the result is the same.

Would a 'waitfor' looking for connection refused help here perhaps?

Replies are listed 'Best First'.
Re^5: Problem with Net::SSH::Expect on unavailable hosts
by jrsimmon (Hermit) on Jul 02, 2009 at 13:58 UTC
    Did you try the timeout setting that I suggested above? What was the result? To really be thorough, capture the debug output from one of your sessions and post it. That will tell you (and us) exactly what Expect is doing underneath the covers. I don't expect I'd be able to decipher it, but others here could.
      I tried the timeout, but the result was the same. The debugging output that I get basically shows nothing from $!, and the return value of $ssh->run_ssh() is always 1, regardless if it's a success or failure.

      Here is the result of enabling debugging (for the offending server -- hugger):

      Spawned 'ssh -e none sebrint@hugger' spawn id(4) Pid: 22388 Tty: /dev/pts/7 Expect::spawn('Expect=GLOB(0x8074f40)','ssh -e none sebrint@h +ugger') called at /vol/perl/5.8/lib/site_perl/5.8.1/Net/SSH/Expect.pm + line 132 Net::SSH::Expect::run_ssh('Net::SSH::Expect=ARRAY(0x8074f58)') + called at ./dumpadm_oz.pl line 33 eval {...} called at ./dumpadm_oz.pl line 32 Starting EXPECT pattern matching... Expect::expect('Expect=GLOB(0x8074f40)',2,'-re','(?-xism:[\s\S +]+)') called at /vol/perl/5.8/lib/site_perl/5.8.1/Net/SSH/Expect.pm l +ine 580 Net::SSH::Expect::_sec_expect('Net::SSH::Expect=ARRAY(0x8074f5 +8)',2,'-re','(?-xism:[\s\S]+)') called at /vol/perl/5.8/lib/site_perl +/5.8.1/Net/SSH/Expect.pm line 419 Net::SSH::Expect::read_all('Net::SSH::Expect=ARRAY(0x8074f58)' +,2) called at ./dumpadm_oz.pl line 47 ssh: connect to host hugger port 22: Connection refused Starting EXPECT pattern matching... Expect::expect('Expect=GLOB(0x8074f40)',2,'-re','(?-xism:[\s\S +]+)') called at /vol/perl/5.8/lib/site_perl/5.8.1/Net/SSH/Expect.pm l +ine 580 Net::SSH::Expect::_sec_expect('Net::SSH::Expect=ARRAY(0x8074f5 +8)',2,'-re','(?-xism:[\s\S]+)') called at /vol/perl/5.8/lib/site_perl +/5.8.1/Net/SSH/Expect.pm line 420 Net::SSH::Expect::read_all('Net::SSH::Expect=ARRAY(0x8074f58)' +,2) called at ./dumpadm_oz.pl line 47 Closing spawn id(4). Expect::hard_close('Expect=GLOB(0x8074f40)') called at /vol/pe +rl/5.8/lib/site_perl/5.8.1/Expect.pm line 894 Expect::_multi_expect(2,'undef','ARRAY(0x81a82b8)') called at +/vol/perl/5.8/lib/site_perl/5.8.1/Expect.pm line 565 Expect::expect('Expect=GLOB(0x8074f40)',2,'-re','(?-xism:[\s\S +]+)') called at /vol/perl/5.8/lib/site_perl/5.8.1/Net/SSH/Expect.pm l +ine 580 Net::SSH::Expect::_sec_expect('Net::SSH::Expect=ARRAY(0x8074f5 +8)',2,'-re','(?-xism:[\s\S]+)') called at /vol/perl/5.8/lib/site_perl +/5.8.1/Net/SSH/Expect.pm line 420 Net::SSH::Expect::read_all('Net::SSH::Expect=ARRAY(0x8074f58)' +,2) called at ./dumpadm_oz.pl line 47 spawn id(4) closed. SSHProcessError The ssh process was terminated. at ./dumpadm_oz.pl lin +e 47 Closing spawn id(4). Expect::hard_close('Expect=GLOB(0x8074f40)') called at /vol/pe +rl/5.8/lib/site_perl/5.8.1/Expect.pm line 1621 Expect::DESTROY('Expect=GLOB(0x8074f40)') called at ./dumpadm_ +oz.pl line 0 eval {...} called at ./dumpadm_oz.pl line 0

      Thanks!
        Ok, after looking into Expect a bit more, I think we've made this a bit more complicated than it needs to be. The read_all() method of Net::SSH::Expect calls the get_expect() in the same package. Per the doc, the get_expect() method will die if the Expect object does not have a valid ssh connection. So...Just wrap your call to read_all() in an eval to catch the die and you should be good. You're original code, modified in this way:
        my $ssh = Net::SSH::Expect->new ( host => "$current_server", user => "$user", raw_pty => 1 ); # test the login eval { $login_output = $ssh->run_ssh(); }; # I've tried to capture $@ or $! here but it never gives me an +ything useful my $rc = eval{($ssh->read_all(2) =~ />\s*|$\s*\z/) or die "whe +re's the remote prompt?";}; unless($rc =~ /$your_expected_output_match_pattern/){ &MOVE_ON_TO_THE_NEXT_HOST; } $ssh->exec("stty raw -echo");
        There are some other things that you should probably clean up in this example, like the poorly named $login_output and not checking the return value of the first eval (or $login_output for that matter). I'll assume you either plan to do that or were just a bit too aggressive in summarizing your code for this example.
        Ok, this is straight out of a script I use frequently to setup a ssh tunnel. Replace $ssh->login() with your call to $ssh->run_ssh() or modify your script to use id/pwd auth. I haven't been able to recreate the script bombing out, so I'm not sure whether this will fix your problem or not -- speaking of which, have you made sure that you're at the current level for Net::SSH::Expect?
        #sometimes the connection isn't ready to login yet, so we try up to +max_retry_count times before giving up my $retry_count = 0; while(1){ $rc = eval{$ssh->login();}; last if defined $rc; last if $retry_count >= $max_retry_count; $retry_count++; sleep 1; }
        Now that I've looked at Expect.pm a little more closely, I can see that I'm not using $ssh->login() correctly...but it does seem to work. So give it a shot and I'll look for a better way of doing the retry loop.