1

我需要运行一个程序,在它的标准输入上输入一些字符串,读取它的标准输出/标准错误并知道它是如何结束的。我必须知道它是否收到信号(段错误等)及其退出代码。此外,如果程序运行时间超过一定时间,我必须知道它(并杀死它)。

你会怎么做?有没有处理这种事情的模块?

4

2 回答 2

1

关于。退出代码和信号,请参见此处。尤其:

129-255 范围内的退出代码表示由 Unix“信号”终止的作业。每种类型的信号都有一个编号,作为作业退出代码报告的是信号编号加上 128。信号可以来自进程本身(对于 SEGV,见下文)或由某些外部代理发送到进程(例如批处理控制系统,或者您使用“bkill”命令)。

例如,退出代码 64 表示作业通过调用“exit(64)”故意终止其执行,退出代码 137 表示作业收到信号 9,退出代码 140 表示信号 12。

于 2012-11-06T13:03:03.353 回答
0

好的,这就是我想出的:(最后的用法示例)

#!/usr/bin/perl
use strict;
use warnings;
use IPC::Open3;
use Symbol 'gensym';
use Time::HiRes 'time';
use POSIX ':sys_wait_h';
use IO::Select;

sub run_prog {
    my ($progin, $timeout, $cmd, @args) = @_;
    my ($progres, $progout, $progerr);
    my ($fdin, $fdout, $fderr);

    my $outsel = IO::Select->new();
    my $errsel = IO::Select->new();

    $fderr = gensym;
    my $pid = open3($fdin, $fdout, $fderr, $cmd, @args);


    my $start = time;

    syswrite $fdin, $progin;
    close $fdin;

    $outsel->add($fdout);
    $errsel->add($fderr);

    $progout = '';
    $progerr = '';

    my $last_activity = $start;
    my $select_timeout = 0.1;

    my $ret;
    while(time - $last_activity < $timeout) {
        if($outsel->can_read($select_timeout)) {
            my $buf;
            $ret = sysread($fdout, $buf, 1000);
            if(!defined $ret) {
                warn "out ndef";
                last;
            }
            $progout .= $buf;
            $last_activity = time;
        }

        if($errsel->can_read($select_timeout)) {
            my $buf;
            $ret = sysread($fderr, $buf, 1000);
            if(!defined $ret) {
                warn "err ndef";
                last;
            }
            $progerr .= $buf;
            $last_activity = time;
        }

        $ret = waitpid($pid, WNOHANG);
        # still exists, continue
        if($ret == 0) {
            next;
        }
        # process exited/signaled
        elsif($ret > 0) {
            $progres = $?;
            last;
        }
        # process doesn't exists??
        else {
            die "wat";
        }
    }

    close $fdout;
    close $fderr;

    # timeout
    if(time - $last_activity >= $timeout) {
        kill 9, $pid;
        waitpid($pid, 0);
        $progres = $?;
    }

    return ($progres, $progout, $progerr);
}

my @r = run_prog("qsdjkqsodj\nqsdqsd\n", 0.9, './bbb', $ARGV[0] || 0);

printf "out: <%s>\nerr: <%s>\n", $r[1], $r[2];
my $x = $r[0];

if ($x == -1) {
    print "failed to execute: $!\n";
}
elsif ($x & 127) {
    printf "child died with signal %d, %s coredump\n",
    ($x & 127),  ($x & 128) ? 'with' : 'without';
}
else {
    printf "child exited with value %d\n", $x >> 8;
}
于 2012-11-06T19:40:52.957 回答