Я создал сценарий в жемчуге для запущения программ с тайм-аутом. Если выполненная программа занимает больше времени затем тайм-аут, чем сценарий закрывает эту программу и возвращает сообщение "ТАЙМ-АУТ".
Сценарий работал вполне хорошо, пока я не решил перенаправить вывод выполненной программы.
Когда stdout и stderr перенаправляются, программа, выполняемая сценарием, не закрывается, потому что это имеет pid, отличающийся, чем тот, который я получил от ветвления.
Кажется, что жемчуг выполняет оболочку, которая выполняет мою программу в случае перенаправления.
Я хотел бы иметь перенаправление вывода, но все еще смочь закрыть программу в случае тайм-аута.
Какие-либо идеи о том, как я мог сделать это?
Упрощенный код моего сценария:
#!/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($?);
Спасибо за любую справку.
Попробуйте изменить $ 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 сам не знает, как с ними обращаться. Альтернативный способ решения проблемы - это сделать перенаправление в самом perl после fork ()
, но до вызова exec ()
- но это немного сложнее, поэтому сначала попробуйте обходной путь exec
!)
Альтернативой является перенаправление STDOUT и STDERR после форка и выполнение команды без перенаправления:
open(STDOUT, ">", "out.txt") or die "Err: $!";
open(STDERR, ">&STDOUT");
exec("very_long_command");
die "Failed to exec very_long_command: $!";