为什么使用tcpreplay的脚本不等待用户输入?

时间:2016-04-03 13:48:30

标签: perl tcpreplay

以下代码段只会等待用户第一次点击 Enter ;之后,它会遍历所有其余的.pcap文件,而无需等待用户输入。

$| = 1;

while (<*.pcap>) {
    print "$_";
    <STDIN>;

    system("tcpreplay -i eth0 -M 20 $_");
}

为什么这不会在每次循环迭代时等待用户输入?

2 个答案:

答案 0 :(得分:2)

你关心Decode输出吗?重定向stdout和stderr似乎解决了这个问题:

tcpreplay

或者,您可以使用它来捕获system("tcpreplay -i eth0 -M 20 $_ >/dev/null 2>&1"); 输出:

tcpreplay

答案 1 :(得分:1)

tcpreplay sets STDIN to use non-blocking I/O,如果没有可用数据,会导致读取立即返回错误。您可以通过检查readline

的返回值来查看此内容
use strict;
use warnings 'all';
use 5.010;

$| = 1;

while (<*.pcap>) {
    say;
    die "readline error: $!" if ! defined <STDIN>;

    system("tcpreplay -i eth0 $_") == 0
        or die "tcpreplay failed: $?";
}

第一次调用tcpreplay后,这会消失:

  

readline错误:./replay第10行暂时无法使用资源,&lt; STDIN&gt;第1行。

这对应于errno EAGAIN,如果标记为非阻塞的文件描述符必须阻塞等待I / O,则read返回。

如果您的系统实现fcntl,您可以通过将STDIN设置为在每次调用tcpreplay后使用阻止I / O来解决此问题:

use strict;
use warnings 'all';
use 5.010;

use Fcntl;

$| = 1;

while (<*.pcap>) {
    say;
    die "readline error: $!" if ! defined <STDIN>;

    system("tcpreplay -i eth0 $_") == 0
        or die "tcpreplay failed: $?";

    # Reset STDIN to use blocking I/O
    my $flags = fcntl(STDIN, F_GETFL, 0) 
        or die "Couldn't get flags for STDIN: $!";
    fcntl(STDIN, F_SETFL, $flags & ~O_NONBLOCK) 
        or die "Couldn't set flags for STDIN: $!";
}

这只是一种解决方法; tcpreplay应该修复。