/ / Nie można pobrać polecenia systemowego, aby przekroczyć limit czasu w skrypcie perl - perl

Nie można uzyskać polecenia systemowego, aby przekroczyć limit czasu w skrypcie perl - perl

Przejrzałem i przeczytałem kilka innych pytań dotyczących uzyskiwania polecenia, aby przestać działać po pewnym czasie, ale wszystko, co próbowałem, nie działa.

Polecenie będzie działać tak, jakby chciało się zatrzymać po upływie określonego czasu (zwraca komunikat terminala na krótką chwilę), ale po prostu kontynuuje i nie zatrzymuje się.

Oto mój kod:

#!/usr/bin/perl

use strict;
use warnings;


use Try::Tiny;

try {
local $SIG{ALRM} = sub { die "alarmn" };
alarm 5;
system("ping 192.168.1.1");
alarm 0;
}
catch {
die $_ unless $_ eq "alarmn";
print "timed outn";
};
exit;

Wyjście w terminalu wygląda tak:

PING 192.168.1.1 (192.168.1.1) 56(84) bytes of data.
64 bytes from 192.168.1.1: icmp_seq=1 ttl=64 time=1.98 ms
64 bytes from 192.168.1.1: icmp_seq=2 ttl=64 time=3.13 ms
64 bytes from 192.168.1.1: icmp_seq=3 ttl=64 time=3.20 ms
64 bytes from 192.168.1.1: icmp_seq=4 ttl=64 time=3.17 ms
64 bytes from 192.168.1.1: icmp_seq=5 ttl=64 time=3.16 ms
64 bytes from 192.168.1.1: icmp_seq=6 ttl=64 time=3.11 ms
64 bytes from 192.168.1.1: icmp_seq=7 ttl=64 time=3.18 ms
64 bytes from 192.168.1.1: icmp_seq=8 ttl=64 time=3.20 ms
64 bytes from 192.168.1.1: icmp_seq=9 ttl=64 time=3.22 ms
64 bytes from 192.168.1.1: icmp_seq=10 ttl=64 time=3.20 ms
skilo@hp-xubuntu:~/perlstuff$ 64 bytes from 192.168.1.1: icmp_seq=11 ttl=64 time=3.06 ms
64 bytes from 192.168.1.1: icmp_seq=12 ttl=64 time=3.19 ms
64 bytes from 192.168.1.1: icmp_seq=13 ttl=64 time=3.21 ms
64 bytes from 192.168.1.1: icmp_seq=14 ttl=64 time=3.21 ms

Zauważ, jak próbuje się zatrzymać, ale nie może.

Odpowiedzi:

4 dla odpowiedzi № 1

Wbudowana funkcja perl „system” rozbija proces, aw procesie potomnym utworzonym przez widelec wykonuje program „ping”. Następnie proces nadrzędny czeka na zakończenie procesu potomnego.

Twój budzik i program obsługi sygnału przerywają proces oczekiwania, a następnie kończą proces rodzicielski, pozostawiając proces potomny uruchomiony w tle.

To, co musisz zrobić, to:

  1. Po upływie czasu alarmu zabij proces potomny, wysyłając mu sygnał
  2. Nadal powinieneś (ręcznie) czekać na proces, aby uniknąć zombie.

Spróbuj tego:

#!/usr/bin/perl

use strict;
use warnings;



eval {
local $SIG{ALRM} = sub { die "alarmn" };
alarm 5;
system("ping -v 192.168.1.1");
alarm 0;
};
if ($@) {
die $@ unless $@ eq "alarmn";
print "timed outn";
kill 2, -$$;
wait;
};
exit;

Uwaga: w moim systemie nie miałem Try :: Tiny, więc zastąpiłem go starymi blokami eval. Ale to powinno działać tak samo.

To polecenie „zabij” pobiera numer sygnału (użyłem2 dla SIGINT, co jest równoważne naciśnięciu ctrl-c) i jednego lub więcej procesów do zabicia. $$ jest pid bieżącego procesu; wartość ujemna powoduje zabicie całej grupy procesów związanej z bieżącym procesem (co w praktyce oznacza wszystkie procesy potomne). Zauważ, że nie jest to całkowicie przenośne - jeśli okaże się, że nie działa w twoim systemie, będziesz musiał znaleźć rzeczywisty PID procesu potomnego. Aby móc to zrobić, należy zastąpić system wywołaniami fork, a następnie exec, w ten sposób:

#!/usr/bin/perl

use strict;
use warnings;


my $childPid;
eval {
local $SIG{ALRM} = sub { die "alarmn" };
alarm 5;
if ($childPid = fork()) {
wait();
} else {
exec("ping -v 192.168.1.1");
}
alarm 0;
};
if ($@) {
die $@ unless $@ eq "alarmn";
print "timed outn";
kill 2, $childPid;
wait;
};
exit;