Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/perl/11.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Perl尝试在不阻塞的情况下从filehandle读取行_Perl - Fatal编程技术网

Perl尝试在不阻塞的情况下从filehandle读取行

Perl尝试在不阻塞的情况下从filehandle读取行,perl,Perl,我正在编写一个简单的实用程序,用于测试到几个主机的往返时间,并选择平均最快的主机。然而,以串行方式而不是并行方式执行此操作需要一段时间,因此我为每个主机生成一个ping进程并从中读取。在我的用例中,scalar操作在读取行之前阻塞已经足够好了,因为我无法避免等待最慢的主机超时。但如果我只想得到最快的k主机,而不关心其他主机,这是一个糟糕的方法。是否有一种方法可以尝试读取具有特定时间限制的完整行,并且在超过时间限制时不消耗任何字节而失败 use strict; use warnings FATAL

我正在编写一个简单的实用程序,用于测试到几个主机的往返时间,并选择平均最快的主机。然而,以串行方式而不是并行方式执行此操作需要一段时间,因此我为每个主机生成一个ping进程并从中读取。在我的用例中,
scalar
操作在读取行之前阻塞已经足够好了,因为我无法避免等待最慢的主机超时。但如果我只想得到最快的k主机,而不关心其他主机,这是一个糟糕的方法。是否有一种方法可以尝试读取具有特定时间限制的完整行,并且在超过时间限制时不消耗任何字节而失败

use strict;
use warnings FATAL => 'all';

# generate command to get average 
# round trip length to hostname.
# we know in advance that each command only
# emits one line
sub command {
    my $host = shift;
    qq(ping -w 1 -c 5 '$host' |) . 
    q(tail -n 1 |) .
    q(sed 's/^.*= //;s/ ms//' |) .
    q(awk -F '/' 'END {print $2}');
}

# launch each ping in its own process and create
# a filehandle that reads from it
sub filehandles {
    my @handles;
    for my $command (@_) {
        open my $fh, '-|', $command or
        die "cannot open file ($!) associated with $command";
    push @handles, $fh;
    }
    @handles;
}

my @commands = map command($_), qw[google.com cnn.com wikipedia.org];
my @fhs = filehandles(@commands);

# read line from each of the ping processes sequentially
for my $fh (@fhs) {
    my $line = scalar <$fh>;
    chomp $line;
    printf "%s\n", $line || '+INF';
}
使用严格;
使用警告致命=>“全部”;
#生成命令以获得平均值
#到主机名的往返长度。
#我们事先知道,每个命令
#发出一条线
副司令部{
我的$host=shift;
qq(ping-w1-c5'$host'|)。
q(尾-n1 |)。
q(sed的/^.*=/;s/ms/'|)。
q(awk-F'/''END{print$2}');
}
#在其自己的流程中启动每个ping并创建
#从中读取的文件句柄
子文件句柄{
我的@手柄;
对于我的$command(@){
打开我的$fh、-|、$command或
die“无法打开与$command关联的文件($!);
推@手柄,$fh;
}
@手柄;
}
my@commands=map command($)、qw[google.com cnn.com wikipedia.org];
my@fhs=filehandles(@commands);
#按顺序从每个ping进程读取行
我的$fh(@fhs){
我的$line=标量;
chomp$行;
printf“%s\n”,$line | |“+INF”;
}

我想我可能会像这样解决您的问题:

#!/usr/bin/perl

use strict;
use warnings;

my $wait_for = 3; #wait for first 3
my @host_list = qw ( server1 server2 server3 server4 ); 

my %host_for; 

foreach my $host ( @host_list ) {
   my $pid = fork; 
   if ( $pid ) { 
       $host_for{$pid} = $host;
   } 
   else {
       my $result = `ping -w 1 -c 5 $host`; 
       last; #so we don't fork bomb 
   }
}

for ( 1..$wait_for ) {
   my $return_pid  = waitpid ( -1, 0 );
   print "Process $return_pid for $host_for{$return_pid} returned\n"; 
}

$SIG{'CHLD'} = 'IGNORE'; #we no longer care about return codes of any still running forks. 
这里可能还有一些优化——我想您可以使用
exec
来减少分叉时的流程开销,而不是使用回退标记。 (或网络::Ping)

但是这个想法是很清楚的-分叉很多次,收获N个分叉,然后将它们的PID与一个散列匹配以执行IPC,而不必担心返回代码。尽管您可能应该检查fork的返回代码,只是为了确保ping没有完全失败


Waitpid会给你美元吗?这将让你测试成功

你知道网::平,我不知道它是否有雇用超时,但它有超时..我没有。谢谢如果我想使用此模块并行或同时执行多个ping,我必须使用多个进程。您可以调用
select
(select RBITS,WBITS,EBITS,TIMEOUT)或
IO::select
()。要获得最快的k响应,请在循环中调用它,并跟踪每次通过的响应数量。使用
Net::Ping
和线程或
Parallel::ForkManager
实际上可以很好地工作。@maxlybert在使用IO::Select时,如何跟踪哪个句柄是哪个句柄?在最初的示例中,我依靠数组中的每个句柄位置来标识输出与哪个主机关联。编辑:显然我可以使用refhash。