带有子进程的 perl 警报 [英] perl alarm with subprocess

查看:41
本文介绍了带有子进程的 perl 警报的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个 perl 脚本,它运行一系列用于回归测试的批处理脚本.我想在批处理脚本上实现超时.我目前有以下代码.

I have a perl script that runs a series of batch scripts for regression testing. I want to implement a timeout on the batch scripts. I currently have the following code.

    my $pid = open CMD, "$cmd 2>&1 |";
    eval {
               # setup the alarm
               local $SIG{ALRM} = sub { die "alarm\n" };
               # alarm on the timeout
               alarm $MAX_TIMEOUT;
               log_output("setting alarm to $MAX_TIMEOUT\n");

               # run our exe
               while( <CMD> ) {
                       $$out_ref .= $_;
               }
               $timeRemaining = alarm 0;
            };
            if ($@) {
                    #catch the alarm, kill the executable
            }

问题是,无论我将最大超时设置为多少,警报都不会触发.我试过使用 Perl::Unsafe::Signals 但这没有帮助.

The problem is that no matter what I set the max timeout to, the alarm is never tripped. I've tried using Perl::Unsafe::Signals but that did not help.

如果我希望能够捕获它们的输出,这是执行批处理脚本的最佳方式吗?有没有另一种方法可以做同样的事情,让我可以使用警报,或者除了警报之外还有其他方法可以使程序超时吗?

Is this the best way to execute the batch scripts if I want to be able to capture their output? Is there another way that would do the same thing that would allow me to use alarms, or is there another method besides alarms to timeout the program?

我已经构建了一个测试脚本来确认警报在我的 perl 和 windows 版本上工作,但是当我运行这样的命令时它不起作用.

I have built a test script to confirm that alarm works on with my perl and windows version, but it does not work when I run a command like this.

我在 windows 7 x64 上使用 activeperl 5.10.1 运行它.

I'm running this with activeperl 5.10.1 on windows 7 x64.

推荐答案

很难判断 alarm 什么时候起作用,系统调用什么时候会被 SIGALRM 中断,相同的代码在不同的操作系统上的表现如何不同,等等.

It's hard to tell when alarm will work, when a system call will and won't get interrupted by a SIGALRM, how the same code might behave differently on different operating systems, etc.

如果您的工作超时,您想终止您已启动的子进程.这是穷人报警的一个很好的用例:

If your job times out, you want to kill the subprocess you have started. This is a good use case for the poor man's alarm:

my $pid = open CMD, "$cmd 2>&1 |";
my $time = $MAX_TIMEOUT;

my $poor_mans_alarm = "sleep 1,kill(0,$pid)||exit for 1..$time;kill -9,$pid";
if (fork() == 0) {
    exec($^X, "-e", $poor_mans_alarm);
    die "Poor man's alarm failed to start";  # shouldn't get here
}
# on Windows, instead of  fork+exec, you can say
#    system 1, qq[$^X -e "$poor_mans_alarm"]


...

穷人的警报在单独的进程中运行.每一秒,它都会检查标识符为 $pid 的进程是否还活着.如果进程不活动,则警报进程退出.如果进程在 $time 秒后仍然活着,它会向进程发送一个终止信号(我使用 9 使其无法捕获,使用 -9 取出整个子进程树,您的需求可能会有所不同).

The poor man's alarm runs in a separate process. Every second, it checks whether the process with identifier $pid is still alive. If the process isn't alive, the alarm process exits. If the process is still alive after $time seconds, it sends a kill signal to the process (I used 9 to make it untrappable and -9 to take out the whole subprocess tree, your needs may vary).

(exec 实际上可能不是必需的.我使用它是因为我也使用这个习语来监视可能比启动它们的 Perl 脚本更长寿的进程.因为情况并非如此这个问题,你可以跳过 exec 调用并说

(The exec actually may not be necessary. I use it because I also use this idiom to monitor processes that might outlive the Perl script that launched them. Since that wouldn't be the case with this problem, you could skip the exec call and say

if (fork() == 0) {
    for (1..$time) { sleep 1; kill(0,$pid) || exit }
    kill -9, $pid;
    exit;
}

相反.)

这篇关于带有子进程的 perl 警报的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆