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. | [reply] [d/l] [select] |
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.
| [reply] |
From Expect.pm in the Net::SSH package:
sub run_ssh {
my Net::SSH::Expect $self = shift;
#(clipped setting up of user options and flags)
my $exp = new Expect();
#(clipped setting of Expect options based on user opts/flags)
my $success = $exp->spawn($ssh_string);
return (defined $success);
}
$success contains the return value of the spawn method in the Expect object. The spawn method in Expect forks the ssh process. As soon as this method is called, ssh is off and running (and we'd better be thinking in async mode). From what I can tell, the spawn method in Expect only returns undef if fork fails or if it's unable to sync with the child process immediately after the fork (I assume to confirm that the process started). Except for those two instances, the eventual return value of run_ssh is going to be positive.
I'll admit, I have some trouble reading the Expect module. So perhaps I'm missing something...but my experience with this module and the quick test script I wrote earlier both support my conclusion. | [reply] [d/l] |
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? | [reply] [d/l] |
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.
| [reply] |