A very simple code to connect to a server, run some commands, disconnect and run some more commands locally.
#!/usr/bin/perl
use strict;
use warnings;
use Expect;
my $timeout = 15;
my $password = "1234";
my $expect = new Expect;
$expect->raw_pty(1);
$expect->spawn("bash\n");
$expect->send("echo run some initial commands locally\n"); # edit: added this line
$expect->send("ssh 1.2.3.4\n");
$expect->expect($timeout,
[ qr/password/,
sub {
$expect->send("$password\n");
}
]
);
$expect->expect($timeout, [ qr/prompt/ ] );
$expect->send("echo run some commands on the server\n");
$expect->send("exit\n"); # disconnect from the server
$expect->send("echo run some more commands locally\n");
$expect->send("exit\n"); # exit bash
$expect->soft_close();
This code works right until the first exit
command. It disconnects from the server but then the entire script seems to freeze. No other commands are executed and I have to Ctrl+C or wait until it times out.
Edit: It works when I execute commands locally, it works when I execute some remotely, then I want to return to working locally but I can't.
Also, I'd like to do the same with nested ssh
's - connect to one server, connect from it to another and so on... and work on all of them.
What am I doing wrong? How can I achieve the desired behaviour?
Apparently right after $expect->send("exit\n");
the script is still trying to send messages to the remote server or to no one (as it's in the process of disconnecting). The solution is to use expect
with a prompt text from the local server (but make sure to use pattern that only matches the local prompt and not the remote one!):
$expect->expect($timeout, [ qr/local_prompt/ ] );
or use some kind of delay (send_slow
, sleep of some kind, etc...).