简体   繁体   English

Perl如何正确处理系统命令(包括带有Kill和RC / STDERR / STDOUT捕获的超时)

[英]Perl how to properly handle System Commands (including Timeout with Kill & capture of RC/STDERR/STDOUT)

From a Perl script I want to execute various system commands and process the output in my script. 从Perl脚本中,我想执行各种系统命令并处理脚本中的输出。

The script will be run automatically, so I want to make sure that no commands are hanging etc. 该脚本将自动运行,因此我想确保没有命令挂起等。

I'm open to any kind of feedback. 我愿意接受任何形式的反馈。

My requirements for the command execution: 我对命令执行的要求:

  • Timeout -> If command runs longer than XX Seconds, it should kill its process(es) 超时->如果命令运行时间超过XX秒,则该命令应终止其进程
  • If command returns information, it should not have to wait for end of timeout 如果命令返回信息,则不必等待超时结束
  • I want to capture the exit status, STDERR, STDOUT in the script. 我想在脚本中捕获退出状态,STDERR,STDOUT。

Here is an example I worked out from an other stackoverflow question: Kill a hung child process 这是我从另一个stackoverflow问题得出的示例: 杀死一个挂起的子进程

What's not working for me at the moment: 目前对我不起作用的是:

  • cannot capture exit status of executed command 无法捕获已执行命令的退出状态
  • cannot capture STDERR of executed command 无法捕获已执行命令的STDERR

Code: 码:

my $cmd = "sleep 15"; # other tests i use -> "echo bla" and "alkjdsf"
my $TIMEOUT = 10;

my $pid = open my $proc, '-|', "$cmd";

if (fork() == 0) {
    my $poor_mans_alarm = "sleep 1,kill 0,$pid ||exit for 1..$TIMEOUT;kill 9,$pid";
    # run poor man's alarm in a background process
    exec($^X, '-e', "$poor_mans_alarm");
}

my $process_output = "";
while (<$proc>) {
   $process_output .= $_;
}

If you either have a trick for this code or recommend a completely different solution, let me know. 如果您对此代码有窍门或推荐一个完全不同的解决方案,请告诉我。

Thanks and cheers 谢谢和欢呼



Addition: 加成:

Got a working Example with IPC::Open3, But for future reader please Check out IPC::Run which has a Timeout Functionality included, as mentioned by James Green. 使用IPC :: Open3获得了一个有效的示例,但是对于以后的读者,请查看包含Timeout功能的IPC :: Run,如James Green所述。

Working example with IPC::Open3: IPC :: Open3的工作示例:

my $pid = open3(\*WRITE, \*READ,\*ERROR,"$command");

if (fork() == 0) {
    my $poor_mans_alarm = "sleep 1,kill 0,$pid ||exit for 1..10;kill 9,$pid";
    # run poor man's alarm in a background process
    exec($^X, '-e', "$poor_mans_alarm");
}


# get all the STDOUT and STDERR from the Child.
while (<READ>) {
   $output .= $_;
}

while (<ERROR>) {
   $output .= $_;
}

waitpid($pid, 0);
if ($?) {
    $rc = $? >> 8;
    if ($rc != 1){
        print "Some error $?\n";
    }
}

It looks like IPC::Run provides pretty much everything you're after, including timeouts and capture of both STDOUT and STDERR. 看起来IPC::Run提供了您所需要的几乎所有东西,包括超时以及STDOUT和STDERR的捕获。 Docs are at https://metacpan.org/pod/IPC::Run including some usage examples. 文档位于https://metacpan.org/pod/IPC::Run,其中包括一些用法示例。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM