以下片段只會等待用戶點擊第一次輸入;之後,它會循環瀏覽所有其餘的.pcap
文件,而無需等待用戶輸入。爲什麼使用tcpreplay的腳本不等待用戶輸入?
$| = 1;
while (<*.pcap>) {
print "$_";
<STDIN>;
system("tcpreplay -i eth0 -M 20 $_");
}
爲什麼不等待每次循環迭代時的用戶輸入?
以下片段只會等待用戶點擊第一次輸入;之後,它會循環瀏覽所有其餘的.pcap
文件,而無需等待用戶輸入。爲什麼使用tcpreplay的腳本不等待用戶輸入?
$| = 1;
while (<*.pcap>) {
print "$_";
<STDIN>;
system("tcpreplay -i eth0 -M 20 $_");
}
爲什麼不等待每次循環迭代時的用戶輸入?
你關心tcpreplay
輸出嗎?重定向輸出和錯誤似乎解決這個問題:
system("tcpreplay -i eth0 -M 20 $_ >/dev/null 2>&1");
或者,你可以用它來捕捉tcpreplay
輸出:
my $tcpreplay_output = `tcpreplay -i eth0 -M 20 $_ 2>&1`;
感謝您的解決方法,它效果很好。不知道爲什麼原來的行爲如此。 – packetie
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 error: Resource temporarily unavailable at ./replay line 10, <STDIN> line 1.
這相當於給errno EAGAIN
,這read
的回報,如果一個標記爲非阻塞的文件描述符將不得不阻塞以等待I/O。
如果你的系統實現fcntl
,你可以通過設置標準輸入每次調用後使用阻塞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
應該是固定的。
這對我很好#perl -e'while(<*.txt>){print; <>}''爲每次按Enter鍵打印一個文件名。你能在你的系統上測試它嗎? – Borodin
我測試過這個,它適用於一個簡單的案例,但肯定會因'system'調用'tcpreplay'而中斷。它只是跳過超過第一遍的任何內容,並且在將其分配給變量時,僅在第一遍時定義。 –
stevieb
謝謝你們。 「tcpreplay」有些奇怪。不知道是否有任何解決方法。 – packetie