【发布时间】:2019-05-15 04:18:42
【问题描述】:
我正在编写一个需要在 windows 和 linux 中运行的 perl 脚本,它将运行一个进程,如果花费的时间太长,则超时,假设它没有超时,则返回退出代码,并假设退出代码为零返回标准输出它没有超时。我不需要 STDIN 或 STDERR。我尝试使用IPC::run,但无法使用。
我得到的最接近的是IPC::Open3 和waitpid($pid, WNOHANG)。但我遇到了一个障碍。我在 windows 和 linux 上看到了不同的结果。在下面的代码中,我给open3 一个将失败的命令(ping 没有任何参数-z)。在 linux 上,代码立即返回一个否定的退出代码。在 Windows 上,命令超时。在 Windows 命令行上运行 ping google.com -z 立即返回告诉我没有这样的参数。为什么“waitpid”返回零?
use strict;
use warnings;
use POSIX ":sys_wait_h";
use IPC::Open3;
my $inFH;
my $outFH;
my @cmd = ("ping", "google.com", "-z");
my $pid = open3( $inFH, $outFH, 0, @cmd);
my $counter=0;
my $waitret;
my $exitcode;
do{
$counter++;
$waitret = waitpid($pid,WNOHANG);
$exitcode = $?;
}while( !$waitret and ($counter < 4_000_000));
if ($counter >= 4_000_000) {
print "Command timed out\n";
kill(9, $pid);
} else {
print "Exit Code: $exitcode\n";
}
欢迎使用其他解决方案。我使用带有 nohang 的 waitpid 的唯一原因是如果它花费的时间太长就终止该进程。在此期间,我没有任何其他需要做的处理。 我在 windows 上使用 windows 10 草莓 perl 5.28 便携版。我的 debian 机器有 perl 5.24。
【问题讨论】:
-
见IPC::Cmd它有一个超时参数,这样可以避免忙等待循环。另请参阅Timeout for launching a bash command in perl
-
使用 IPC::Cmd 并运行我的脚本似乎耐心地等待进程结束,然后通知我是否违反了超时。使用 'ping google.com /t' 运行会导致运行挂起,等待 ping 停止,即使我将超时设置为 4。在 linux 中它似乎按预期工作。
-
不幸的是,Windows 没有真正的分叉,所以它是通过 ithreads 模拟的。 Windows 也不支持 POSIX 信号。这可能就是您看到不同行为的原因。