Из сценария Perl я хочу выполнять различные системные команды и обрабатывать вывод в моем сценарии.
Скрипт запустится автоматически, поэтому я хочу убедиться, что никакие команды не зависают и т. Д.
Я открыт для любых отзывов.
Мои требования к выполнению команды:
- Тайм-аут -> Если команда выполняется дольше XX секунд, она должна убить свой процесс (ы)
- Если команда возвращает информацию, ей не нужно ждать окончания тайм-аута.
- Я хочу зафиксировать статус выхода, STDERR, STDOUT в скрипте.
Вот пример, который я разработал из другого вопроса о переполнении стека: Убить зависший дочерний процесс
Что у меня не работает на данный момент:
- не может зафиксировать статус выхода выполненной команды
- не может захватить STDERR выполненной команды
Код:
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 .= $_;
}
Если у вас есть трюк с этим кодом или вы порекомендуете совершенно другое решение, дайте мне знать.
Спасибо и ура
Дополнение:
Есть рабочий пример с IPC :: Open3, но для будущих читателей, пожалуйста, ознакомьтесь с IPC :: Run, в котором включена функция тайм-аута, как упоминал Джеймс Грин.
Рабочий пример с 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";
}
}