6

タイムアウトでプログラムを実行するために、perlでスクリプトを作成しました。実行中のプログラムに時間がかかる場合は、スクリプトがこのプログラムを強制終了して「TIMEOUT」というメッセージを返すよりもタイムアウトになります。

実行されたプログラムの出力をリダイレクトすることを決定するまで、スクリプトは非常にうまく機能しました。

stdoutとstderrがリダイレクトされているとき、スクリプトによって実行されたプログラムは、フォークから取得したものとは異なるpidを持っているため、強制終了されません。

perlはリダイレクトの場合に私のプログラムを実行するシェルを実行しているようです。

出力リダイレクトが欲しいのですが、タイムアウトの場合でもプログラムを強制終了できます。

どうすればそれができるかについてのアイデアはありますか?

私のスクリプトの簡略化されたコードは次のとおりです。

#!/usr/bin/perl

use strict;
use warnings;
use POSIX ":sys_wait_h";

my $timeout = 5;
my $cmd = "very_long_program 1>&2 > out.txt";

my $pid = fork();
if( $pid == 0 )
{
   exec($cmd) or print STDERR "Couldn't exec '$cmd': $!";
   exit(2);
}
my $time = 0;
my $kid = waitpid($pid, WNOHANG);
while ( $kid == 0 )
{
   sleep(1);
   $time ++;
   $kid = waitpid($pid, WNOHANG);
   print "Waited $time sec, result $kid\n";
   if ($timeout > 0 && $time > $timeout)
   {
      print "TIMEOUT!\n";
      #Kill process
      kill 9, $pid;
      exit(3);
   }
}

if ( $kid == -1)
{
   print "Process did not exist\n";
   exit(4);
}
print "Process exited with return code $?\n";
exit($?);

助けてくれてありがとう。

4

2 に答える 2

12

$cmdから変更してみてください

my $cmd = "very_long_program 1>&2 > out.txt";

my $cmd = "exec very_long_program 1>&2 > out.txt";

exec、perlによって生成されたシェルに、very_long_programを子として実行するのではなく、very_long_programに置き換えるように指示します。

(この場合、perlがシェルを生成する理由$cmdは、リダイレクト文字が含まれているためです-そしてperlはそれら自体を処理する方法を知りません。問題を解決する別の方法は、fork()呼び出しの前に、perl自体でリダイレクトを行うことです。 exec()-しかし、それは少し難しいので、exec最初に回避策を試してください!)

于 2010-06-03T10:36:24.657 に答える
2

別の方法は、フォークの後にSTDOUTとSTDERRをリダイレクトし、リダイレクトせずにコマンドを実行することです。

open(STDOUT, ">", "out.txt") or die "Err: $!";
open(STDERR, ">&STDOUT");
exec("very_long_command");
die "Failed to exec very_long_command: $!";
于 2010-06-03T15:11:25.430 に答える