为什么这个使用 tcpreplay 的脚本不等待用户输入?
Why does this script that uses tcpreplay not wait for user input?
以下代码段只会等待用户第一次点击 Enter;之后,它会循环遍历所有其余 .pcap
文件,而无需等待用户输入。
$| = 1;
while (<*.pcap>) {
print "$_";
<STDIN>;
system("tcpreplay -i eth0 -M 20 $_");
}
为什么不在每次循环迭代时都等待用户输入?
你关心tcpreplay
输出吗?重定向 stdout 和 stderr 似乎可以解决这个问题:
system("tcpreplay -i eth0 -M 20 $_ >/dev/null 2>&1");
或者,您可以使用它来捕获 tcpreplay
输出:
my $tcpreplay_output = `tcpreplay -i eth0 -M 20 $_ 2>&1`;
tcpreplay
sets STDIN to use non-blocking I/O,如果没有数据可用,这会立即导致读取 return 错误。您可以通过检查 readline
:
的 return 值来查看
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 error: Resource temporarily unavailable at ./replay line 10, <STDIN> line 1.
这对应于 errno EAGAIN
,如果标记为非阻塞的文件描述符必须阻塞以等待 I/O,则 read
returns。 =23=]
如果您的系统实现了 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
应该修复。
以下代码段只会等待用户第一次点击 Enter;之后,它会循环遍历所有其余 .pcap
文件,而无需等待用户输入。
$| = 1;
while (<*.pcap>) {
print "$_";
<STDIN>;
system("tcpreplay -i eth0 -M 20 $_");
}
为什么不在每次循环迭代时都等待用户输入?
你关心tcpreplay
输出吗?重定向 stdout 和 stderr 似乎可以解决这个问题:
system("tcpreplay -i eth0 -M 20 $_ >/dev/null 2>&1");
或者,您可以使用它来捕获 tcpreplay
输出:
my $tcpreplay_output = `tcpreplay -i eth0 -M 20 $_ 2>&1`;
tcpreplay
sets STDIN to use non-blocking I/O,如果没有数据可用,这会立即导致读取 return 错误。您可以通过检查 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 error: Resource temporarily unavailable at ./replay line 10, <STDIN> line 1.
这对应于 errno EAGAIN
,如果标记为非阻塞的文件描述符必须阻塞以等待 I/O,则 read
returns。 =23=]
如果您的系统实现了 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
应该修复。