2

サーバーに接続し、いくつかのコマンドを実行し、切断してローカルでさらにいくつかのコマンドを実行するための非常に単純なコード。

#!/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();

このコードは、最初のexitコマンドまで正しく機能します。サーバーから切断されますが、スクリプト全体がフリーズしているようです。他のコマンドは実行されず、Ctrl+C を実行するか、タイムアウトになるまで待つ必要があります。

編集:コマンドをローカルで実行すると機能し、リモートでコマンドを実行すると機能し、ローカルでの作業に戻りたいのですが、できません。

また、ネストされた 's で同じことをしたいと思いsshます-あるサーバーに接続し、そこから別のサーバーに接続するなど...そしてそれらすべてで作業します。

私は何を間違っていますか?どうすれば望ましい動作を実現できますか?

4

1 に答える 1

2

どうやら$expect->send("exit\n");、スクリプトがまだリモートサーバーにメッセージを送信しようとしているか、誰にもメッセージを送信しようとしていない (切断中のため)。解決策はexpect、ローカル サーバーからのプロンプト テキストを使用することです (ただし、リモート プロンプトではなく、ローカル プロンプトにのみ一致するパターンを使用してください! ):

$expect->expect($timeout, [ qr/local_prompt/ ] );

または、何らかの遅延を使用します(send_slow、何らかのスリープなど...)。

于 2015-05-08T13:14:53.913 に答える