【问题标题】:How can expect get out of infinite loop in a spawned process如何在衍生过程中摆脱无限循环
【发布时间】:2017-09-05 23:06:53
【问题描述】:

让我用一组具体的例子来问这个问题。第一段代码,nlines.pl 如下:

#!/usr/local/bin/perl
#########################
# print Hello world n times with n entered by a prompt
#########################

use strict;
use Time::HiRes qw(sleep);

die "Syntax: $0 <prompt> <time2sleep>\n" if ($#ARGV < 1);
my $prompt = $ARGV[0] . '> ';
my $sleepsec = $ARGV[1];        print "$0: Timeout interval: $sleepsec\n";
print $prompt;
while (<STDIN>) {
        chomp;
        last unless /\d+/;
        my $loopCount = $_;
        print "\n$0: Received request for $loopCount lines\n";
        for (my $count = 0; $count != $loopCount ; $count++) {
                Time::HiRes::sleep($sleepsec) if ($sleepsec > 0);
                print "$0 [$count] Hello world\n"
        }
        print $prompt
}
print "Bye bye\n";
exit 0;

$ nlines.pl pp 0.2 生成提示符“pp>”,当给定输入“6”时,以 0.2 秒的时间间隔打印 6 次“Hello world”(仅当间隔为 +ve 数字时)。非数字输入使您脱离循环,而行数为负数会导致无限循环。工作正常!

现在,考虑将第二个脚本 - “expnlines.pl”作为上述脚本的驱动程序。

#!/usr/local/bin/perl
#############################
# expnlines.pl: driver for nlines.pl
#############################

use strict;
use Expect;

die "Syntax: $0 <Count> <SleepSec>\n" if ($#ARGV < 1);
my $count = $ARGV[0];
my $child = 'nlines.pl';
my $prompt = 'CountOfLines';
my $ex = Expect->new;
$ex->raw_pty(1);
$ex->spawn ($child, $prompt, $ARGV[1]);
$ex->expect (1, $prompt) or die "$0: No prompt from $child\n";
print "$0: Sending $count\n";
$ex->send($count . "\n");
$ex->expect (2, $prompt) or die "\n$0: Expect timed out for $count\n";
print "\n$0: Received prompt back from expect\n";
exit 0;

如果我们将它作为“expnlines.pl 4 0.2”运行,它可以正常工作。 “expnlines.pl -1 0.3”(或其他任何超时)也可以。对于 linecount 的 -ve #,第一个脚本进入无限循环,但预期超时。但是,“expnlines.pl -1 0”无法停止无限循环(在那 2 秒之后),我无法弄清楚如何让期望中断这个循环。

有什么建议吗? TIA。

顺便说一句,在我的现实世界中,我无法控制“nlines.pl”的等效二进制文件。我的脚本是“expnlines.pl”,我使用期望作为二进制驱动程序,具有不同的参数。当子进程运行无限循环时,我需要一些机制来检测和停止它,我不知道如何。感谢您的回复。

【问题讨论】:

    标签: perl expect.pm


    【解决方案1】:

    超时后,您可以使用hard_close(或soft_close,如果您需要很好,并且可以等待它使用的额外时间)关闭命令,终止它,然后无限循环。

    代替

    $ex->expect (2, $prompt) or die "\n$0: Expect timed out for $count\n";
    

    你可以这样做

    if (!$ex->expect(2, $prompt)) {
        print "\n$0: Expect timed out for $count, closing\n";
        $ex->hard_close();
    }
    else {
        print "\n$0: Received prompt back from expect\n";
    }
    

    【讨论】:

    • 试过你的改变,对我不起作用。问题 - 我们永远不会到达您的第二行。想知道这是否是由于操作系统、Perl/Expect 版本等原因。我使用的是 OSX El Capitan v10.11.3、Perl 5.22.1、Expect 1.320.0_0。如果该解决方案适合您,您介意分享您的平台和/或版本吗?谢谢。
    • OSX 10.10.5、Perl 5.20.1 和 Expect 1.32。这对我有用。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2019-01-15
    • 2021-03-17
    • 1970-01-01
    • 1970-01-01
    • 2013-06-20
    • 2016-06-21
    相关资源
    最近更新 更多