От Perl скрипт искам да изпълня различни системни команди и да обработя изхода в моя скрипт.
Скриптът ще се стартира автоматично, така че искам да се уверя, че няма команди, които висят и т.н.
Отворен съм за всякакъв вид обратна връзка.
Моите изисквания за изпълнение на командата:
- Изчакване -> Ако командата се изпълнява по-дълго от XX секунди, тя трябва да убие процеса(ите) си
- Ако командата върне информация, не трябва да чака края на времето за изчакване
- Искам да уловя състоянието на изход, STDERR, STDOUT в скрипта.
Ето един пример, който разработих от друг въпрос на stackoverflow: Убийте увиснал дъщерен процес
Какво не ми работи в момента:
- не може да улови изходния статус на изпълнената команда
- не може да улови 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";
}
}