这是一个小的Perl服务器。它显示(1),接受一行输入,然后显示(2)等。如果输入“error”或“commit”,它会给出一个自定义消息。如果键入“exit”,则退出。否则,它只是无休止地接受输入。
use strict;
use warnings;
$|++;
my $counter = 1;
print "($counter) ";
while (<STDIN>) {
chomp;
if ($_ eq "error") {print "Error on command #$counter\n";}
if ($_ eq "commit") {print "Committing data\n";}
if ($_ eq "exit") {print "Exiting program...\n"; exit;}
$counter++;
print "($counter) ";
}
现在,这是一个Expect.pm客户端脚本,通过键入各行来与服务器脚本进行交互。
use strict;
use warnings;
use Expect;
$|++;
my $exp = new Expect;
$exp->raw_pty(1);
$exp->log_file("/tmp/expect.out");
$exp->log_stdout(1);
my @commands = (
"This is the first command",
"Here is the second command",
"error",
"commit",
"This is the last command",
"exit",
);
$exp->spawn("./expecttest_server.pl");
foreach my $command (@commands) {
print "$command\n";
$exp->send("$command\n");
$exp->expect(1, '-re','\(\d+\)');
}
$exp->soft_close();
我想要的是能够从头到尾存储整个会话,包括服务器脚本生成的所有内容,以及Expect.pm脚本发送的所有内容。
也就是说,我想要我的客户端脚本能够返回这样的输出,如果你手动运行并与服务器脚本交互,你会看到这样:
(1) This is the first command (2) Here is the second command (3) error Error on command #3 (4) commit Committing data (5) This is the last command (6) exit Exiting program...
但运行客户端脚本的STDOUT显示如下所示:
This is the first command (1) (2) Here is the second command error (3) Error on command #3 (4) commit This is the last command Committing data (5) (6) exit Exiting program...
和$ exp-&gt; log_file(tmp / expect.out)指定的文件显示:
(1) (2) (3) Error on command #3 (4) Committing data (5) (6) Exiting program...
我尝试过记录命令本身的各种组合+ $ exp-&gt; expect()返回的 before_match 和 after_match 变量。但到目前为止,我还没有得到正确的组合。这似乎是一种非常笨重的方式来获得我正在寻找的东西。
那么,捕获整个Expect.pm会话的最佳做法是什么?
感谢任何可以提供帮助的人!
答案 0 :(得分:0)
在命令行上运行时,服务器会打印
(1)
立即stdout并等待输入。
但是,当您创建Expect
对象时,实际上是在设置PTY(伪终端)。您spawn
的任何进程都会将其stdin和stdout连接到此PTY,不连接到您的shell所连接的TTY。这意味着由Expect
对象决定是否显示生成进程的输出;它不会自动显示。
当您spawn
进程时,Expect
对象保留在输入缓冲区中的任何输出上。当您send
进程的字符串时,生成的任何其他输出都将被读入缓冲区。如果PTY启用了回显(默认值),您发送的字符串将被回显,但Expect
对象缓冲区的内容不会回显。
当您调用expect
方法时,Expect会等到输入缓冲区中出现匹配的字符串。如果在超时到期之前找到匹配项,expect
将返回并打印匹配的字符串。
因此,您需要做的只是在 expect
第一个命令之前调用send
,如下所示:
use strict;
use warnings;
$| = 1;
my $counter = 1;
do {
print "($counter) ";
$counter++;
} while (<>);
use strict;
use warnings;
use Expect;
$| = 1;
my $exp = Expect->new;
my $server = './expect_server';
$exp->spawn($server);
my @commands = qw(foo bar baz);
foreach my $command (@commands) {
$exp->expect(1, '-re', '\(\d+\)');
$exp->send("$command\r");
}
$exp->soft_close;
(1) foo
(2) bar
(3) baz
(4)
请注意,这与您手动与流程交互时使用的过程完全相同:等待提示,然后键入命令。