3

次のスニペットは、ユーザーがEnter最初にヒットするまで待機します。その後、.pcapユーザーの入力を待たずに、残りのすべてのファイルを循環します。

$| = 1;

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

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

これがループの繰り返しごとにユーザー入力を待たないのはなぜですか?

4

2 に答える 2

2

tcpreplay非ブロッキング I/O を使用するように STDIN を設定します。これにより、データが利用できない場合、読み取りですぐにエラーが返されます。これは、次の戻り値を確認することで確認できます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、<STDIN> 行 1 でリソースが一時的に利用できません。

これは、非ブロッキングとしてマークされたファイル記述子が I/O を待機するためにブロックする必要がある場合に返される errnoEAGAINに対応します。read


システムが を実装fcntlしている場合、STDIN を への呼び出しのたびにブロッキング I/O を使用するように設定することで、これを回避できますtcpreplay

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修正する必要があります。

于 2016-04-06T00:27:19.033 に答える
2

tcpreplayアウトプットを気にしますか?stdout と stderr をリダイレクトすると、この問題が解決するようです。

system("tcpreplay -i eth0 -M 20 $_ >/dev/null 2>&1");

tcpreplayまたは、これを使用して出力をキャプチャできます。

my $tcpreplay_output = `tcpreplay -i eth0 -M 20 $_ 2>&1`;
于 2016-04-03T14:43:25.470 に答える