in reply to Problem with Net::SSH::Expect on unavailable hosts

Try setting a timeout, like so:
my $ssh = Net::SSH::Expect->new ( host => "$current_server", user => "$user", raw_pty => 1, timeout => 5 ); # test the login eval { $login_output = $ssh->run_ssh(); }; # I've tried to capture $@ or $! here but it never gives me an +ything useful ($ssh->read_all(2) =~ />\s*|$\s*\z/) or die "where's the remot +e prompt?"; $ssh->exec("stty raw -echo");
You may also want to look at the exp_debug and log_stdout options.

Replies are listed 'Best First'.
Re^2: Problem with Net::SSH::Expect on unavailable hosts
by mr_mischief (Monsignor) on Jul 01, 2009 at 20:47 UTC
    How does that help? The return value that's being stuffed into $login_output is what needs to be tested to see if run_ssh() was successful or not. $@ and $! are meaningless when they are not the mechanism being used. How about suggesting testing the proper value?
      Without a timeout value, you can attempt to use the ssh connection before run_ssh() has finished what it's doing. This causes crazy stuff, like the script abending. In the op's example, testing the value of $login_output would not have necessarily solved anything. In the test script I wrote, it had no effect whatsoever (was always empty, whether the connection was successful or not). Additionally, adding the debug and log to stdout parms will help to track down what exactly is happening behind the run_ssh() call. If he waits until run_ssh() has finished, the regex check he included from the documentation will correctly determine whether he has a valid connection or not.

      The doc for Net::SSH::Expect does imply $! as the location meaningful error information from run_ssh() with the statement:
      $ssh->run_ssh() or die "SSH process couldn't start: $!";
      The fact that he "received nothing useful" from it leads me to believe he was checking trying to use the connection before run_ssh() had finished trying to connect.
        It leads me to believe that, if by returning a failure state run_ssh() allows you to assume that the subprocess could not start, that it blocks its return until it has started otherwise.

        The docs for run_ssh() further state " boolean: 1 if the ssh ran OK or 0 otherwise. In case of failures, use $! to do get info." Note the tense and order. $! is meaningless unless run_ssh() returned a failure code. It wouldn't return a failure code if the SSH session was started successfully, and doesn't return success until and unless it was started successfully.

        $! is absolutely meaningless regarding the success of run_ssh(), as it will not get populated by run_ssh() except on failure.

        Why do you seem to think that run_ssh() is run asynchonously and does not block? It's the SSH connection that's supposed to be in a separate process per the docs, not run_ssh() itself.

        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?