Istnieją (co najmniej) dwa programy zapewniające tę funkcjonalność:
IMIĘ
timelimit
- skutecznie ograniczać bezwzględny czas wykonania procesu
STRESZCZENIE
timelimit [-pq] [-S killsig] [-s warnsig] [-T killtime] [-t warntime] command [arguments ...]
i
IMIĘ
timeout
- uruchom polecenie z ograniczeniem czasowym
STRESZCZENIE
timeout [OPTION] DURATION COMMAND [ARG]...
timeout [OPTION]
Są one pakowane w następujący sposób:
$ dlocate `which timeout timelimit`
timelimit: /usr/bin/timelimit
coreutils: /usr/bin/timeout
Porównanie:
/-----------------------------+------------+----------------\
| Feature | timelimit | timeout |
+=============================+============+================+
| time to run | -t time | first argument |
+-----------------------------+------------+----------------+
| terminate signal | -s signal | -s signal |
+-----------------------------+------------+----------------+
| grace period | -T time | -k time |
+-----------------------------+------------+----------------+
| kill signal | -S signal | (note 1) |
+-----------------------------+------------+----------------+
| propagate signals | -p | (note 2) |
\-----------------------------+------------+----------------/
Uwagi:
timeout
zawsze używa SIGKILL
jako sygnału ostatecznego.
timeout
nie ma żadnej funkcji wyjścia z sygnałem, gdy program podrzędny to robi.
Status wyjścia tych dwóch programów jest różny, ale trudno to dokładnie podsumować, dlatego sugeruję, abyś sam zajrzał do stron podręcznika.
Ponieważ timeout
jest instalowany domyślnie na większej liczbie systemów ( coreutils
jest to standardowy pakiet w wielu dystrybucjach), sugeruję, abyś go używał, chyba że potrzebujesz dodatkowych funkcji zapewnianych przez timelimit
.
timelimit
. Zobacz Jak mogę zabić proces i upewnij się, że PID nie został ponownie użyty, aby uzyskać więcej informacji na jego temat i przekroczeniu limitu czasu GNU.timeout
jest wliczone w GNU coreutils ,timelimit
nie jest. Możesz zainstalować żaden, jeden lub oba. Po drugie zgłaszane jest, że timelimit wykonuje polecenie i kończy odradzany proces po określonym czasie z danym sygnałem. Najpierw wysyłany jest sygnał „ostrzegawczy” , a następnie po upływie limitu czasu sygnał „zabijania”, podobny do sposobu działania init (8) przy wyłączaniu. Więc nawet inne zachowanie w środku .timeout
jest to droga do tego.W rzeczywistości jest to po
timeout
to:źródło
Czysty
bash
wbudowany, bez rdzeniOdkryłem, że to rozwiązanie działa w
bash
oparciu o wbudowane polecenie bez wywoływania zewnętrznego pliku wykonywalnego. Działa na systemie, na którym ostatecznie nie są nawet zainstalowane coreutils [ 1 ]Objaśnienia : jak zwykle po wysłaniu komendy w tle z
&
jego PID jest przechowywany w zmiennej wewnętrznej$!
(obecne w nowoczesnej wersjidash
,csh
,bash
,tcsh
,zsh
...).To, co naprawdę robi różnicę między powłokami, to obecność wbudowanego polecenia
read
[ 2 ] i opcji-t
. W pierwszej wersji, jeśli użytkownik nie wypełni wiersza wprowadzania przed określoną liczbą sekund, instrukcja zostanie zakończona i wygenerowany zostanie kod powrotu błędu.Druga wersja działa jako pierwsza, ale możesz anulować limit czasu zabijania po prostu naciskając enter.
Rzeczywiście operator lub
||
wykonujekill
instrukcję tylko wtedy, gdyread
polecenie zakończy działanie z kodem powrotu innym niż zero, tak jak po upływie limitu czasu. Jeśli naciśniesz enterprzed tym momentem, zwróci 0 i nie zabije twojego poprzedniego polecenia.Rozwiązania Coreutils [ 1 ]
Gdy w twoim systemie znajdują się coreutils i nie musisz oszczędzać czasu i zasobów, aby wywołać program zewnętrzny,
timeout
isleep
oba są idealnymi sposobami na osiągnięcie celu.timeout
Korzystanie ztimeout
jest proste.W końcu możesz rozważyć skorzystanie z
-k
opcji wysłania dodatkowego sygnału zabicia, jeśli pierwszy się nie powiedzie.sleep
Dziękisleep
niemu możesz wykorzystać swoją fantazję lub czerpać inspiracje [ 3 ] . Pamiętaj, że możesz pozostawić swoje polecenie w tle lub na pierwszym planie (np.top
Zwykle musi znajdować się na pierwszym planie).Objaśnienia
YourCommand
a następnie twoja skorupasleep
przez 5 minut. Kiedy zostanie zakończony, ostatni proces w tle ($!
) zostanie zabity. Zatrzymaj swoją skorupę.YourCommand
i od razu zapisujesz ten PID w zmiennej$pid
. Następnie wykonujesz drzemkę w tle przez 5 minut i wynikające z niej polecenie, które zabije zapisany PID. Ponieważ wysłałeś tę grupę poleceń w tle, nie zatrzymujesz powłoki. Musisz zapisać PID w zmiennej, ponieważ wartość$!
może zostać zaktualizowana przez ewentualne wykonanie innego programu w tle. Krótko mówiąc, unikasz ryzyka zabicia niewłaściwego procesu lub jego braku.$$
, następnie wykonuje polecenie, które pozostaje na pierwszym planie.()
która przechowuje swój PID w zmiennej (cmdpid
) i zabija się za pomocą innej podpowłoki wysyłanej w tle, a następnie uruchamia YourCommand na pierwszym planie.Oczywiście w każdej wersji możesz wysłać potrzebny ci sygnał zabójstwa, od domyślnego do skrajnego
kill -9
, do użycia tylko wtedy, gdy jest naprawdę potrzebny.Bibliografia
źródło
W konkretnym przypadku większość implementacji
ping
wsparcia-c
lub--count
kończy się po określonej liczbie pingów:Aby uzyskać bardziej ogólne rozwiązanie, zobacz inne odpowiedzi.
źródło
ping
konkretny przykład. Nie chce indywidualnych rozwiązań dla każdego innego programu.Możesz to zrobić za pomocą prostego skryptu, takiego jak ten:
(sygnał SIGINT = 2 zastosowany zgodnie z sugestią Matija Nalis w komentarzu poniżej).
Wyjaśnienie (nietypowego?) Wyrażenia bash
$@:...
: parametry pozycyjne, ($*, $@, "$*", "$@"
) dopuszczają następującą dodatkową specyfikację, na przykład:co oznacza: ze wszystkich parametrów, weź COUNT z nich, pierwszy z nich to ten na pozycji START; jeśli pominięto COUNT, weź je wszystkie do końca, zaczynając od pozycji START. Pamiętaj, że
$0
to nazwa programu. Jeśli START jest ujemny, zacznij odliczanie od końca i pamiętaj, że COUNT nie może być ujemny, stąd ostatni argument"${@:-1}"
. Ponadto prawie zawsze uwzględniaj parametry pozycyjne w podwójnych cudzysłowach.źródło
$1
jest dość obrzydliwe. Ponadto możesz po prostusleep "$1"
lub coś w tymcountdown
.time=$1; shift
, a następnie nie potrzebujesz składni krojenia tablic dla parametrów pozycyjnych. Ale tak, to o wiele prostsze.ctrl-c
, prawdopodobnie lepiej jest spróbowaćkill -INT
zamiastkill -9
(lub przynajmniej spróbować-9
po kilku sekundach, jeśli pierwszy nie spowodował błędu - daje to programowi szansę na czyste zamknięcie i nie pozostawianie plików tymczasowych itp. wokół)Ponieważ wspomniałeś
ping
w swoim przykładzie; to polecenie ma kilka opcji zatrzymania po określonym czasie:źródło