Jak ograniczyć czas działania programu w systemie Linux?

10

Mam kilka symulacji do wykonania, z których każda jest wywoływana python simulate.py <parameter list>. Problem z tymi symulacjami polega na tym, że niektóre z nich zawieszają się bez wychodzenia, co uniemożliwia mi uruchamianie ich wsadowo za pomocą prostego skryptu.

Potrzebowałbym jakiejś formy polecenia „ograniczenia w czasie wykonywania”, które automatycznie zabiłoby proces (najlepiej przez naciśnięcie Ctrl + C , ale myślę, że proste zabicie też zrobi) po określonym czasie, jeśli sam proces nie zakończył się z gracją.

Oczywiście mogę sam napisać taki skrypt, ale podejrzewam, że ktoś zrobił to już przede mną, więc nie muszę wymyślać koła, które spędzam godzinami ps, timei bash podręczników.

Adam Ryczkowski
źródło

Odpowiedzi:

15

Potencjalne rozwiązanie nr 1

Użyj timeoutpolecenia:

$ date
Mon May  6 07:35:07 EDT 2013
$ timeout 5 sleep 100
$ date
Mon May  6 07:35:14 EDT 2013

Możesz także ustawić straż w tym timeoutpoleceniu kill, jeśli proces nie zatrzymał się również po pewnym czasie.

$ date
Mon May  6 07:40:40 EDT 2013
$ timeout -k 20 5 sleep 100
$ date
Mon May  6 07:40:48 EDT 2013

Poczeka to do 20 sekund po zakończeniu procesu sleep 100, jeśli nadal trwa, timeoutwyśle ​​mu killsygnał.

Potencjalne rozwiązanie # 2

Alternatywnym sposobem, choć bardziej ryzykowną metodą, byłoby:

./myProgram &
sleep 1
kill $! 2>/dev/null && echo "myProgram didn't finish"

Znalazłem tę technikę na przepełnieniu stosu w pytaniu zatytułowanym: Ograniczanie czasu działania programu w systemie Linux . W szczególności ta odpowiedź .

UWAGA: Na komentarz pozostawiony przez @mattdm powyższa metoda może być ryzykowna, ponieważ zakłada, że ​​od czasu rozpoczęcia procesu nie uruchomiono żadnych nowych procesów. Dlatego nie przypisano żadnych nowych PID. Biorąc to pod uwagę, to podejście prawdopodobnie nie powinno być stosowane, ale jest tu jedynie odniesieniem do ogólnego podejścia do problemu. timeoutMetoda jest lepsza opcja od 2.

slm
źródło
Ale wtedy będzie zagwarantowane, że skrypt zawsze będzie trwał cały czas. W moim przypadku nie jest to 1 sekunda, a raczej 15 minut.
Adam Ryczkowski
Ale inne rozwiązanie znalezione w tym pytaniu powinno być dokładnie tym, czego potrzebuję. Dzięki!
Adam Ryczkowski
2
Załóżmy, że myProgram kończy się w krótszym czasie niż sleep(nie jest to nieuzasadnione założenie, ponieważ celem jest ustawienie maksymalnego dozwolonego czasu wykonywania). Następnie wysyłasz sygnał do nieistniejącego PID (bez wyrządzenia rzeczywistej szkody) lub do dowolnego losowego procesu w systemie (potencjalnie śmiertelny).
CVn
1
@ MichaelKjörling, dzięki za wiadomość. Zaktualizowałem odpowiedź na ten sam komentarz, który pozostawił PO. Wygląda na to, że timeoutpolecenie robi dokładnie to, czego szuka, czekając, aż OP odpowie na moje komentarze.
slm
@slm timeoutpowinno być rozwiązaniem, którego potrzebuję. Obecnie
testuję
4

Znalazłem coś trochę lepiej, niż timeout: timelimit.

Ma kilka zalet; jednym z nich jest to, że użytkownik może ręcznie przerwać wykonywanie, naciskając „Ctrl + C”.

timelimitProgram dostępny jest w repozytorium Debiana.

Adam Ryczkowski
źródło
1
Próbuję zrozumieć różnice między limitem czasowym a limitem czasu. Limit czasu można zatrzymać za pomocą Ctrl + C. Jakie są inne zalety?
slm
Cóż, mój limit czasu nie może. Używam Mint 14 (w oparciu o Ubuntu Quantal).
Adam Ryczkowski
3

Możesz dostroić czas procesora i inne rzeczy ulimit, szczególnie czas procesora:

$ ulimit -t 60      # limit to 60 seconds
$ program
RSFalcon7
źródło
Zobacz poniższe pytania i odpowiedzi dotyczące U&L: unix.stackexchange.com/a/4666/7453 . @Gilles daje dobry przegląd wykorzystania ulimit do tego celu.
slm
0

Bash używa zmiennej o nazwie $BASHPIDto może być użyte w takiej sytuacji, na przykład:

#!/bin/bash
do_face() {
    local parent=$1
    echo $BASHPID > pid
    sleep 10
    echo "Killing parent $parent"
    kill $parent
}

ME=$BASHPID
eval $(echo "do_face $ME &")
sleep 20 && kill $(cat pid) && echo "killed child $(cat pid)"
exit 1

Można zmienić argument w wywołaniu sleepw do_face()celu 100zamiast 10i zobaczyć, co się dzieje, gdy dziecko trwa zbyt długo, aby wykonać swoje obowiązki. Wystarczy zmienić wywołanie uśpienia do_face()na wywołanie pliku wykonywalnego, a jeśli zajmie to zbyt dużo czasu, skrypt go zabije, 20w tym przykładzie wartość graniczna to sekundy. Parametry mogą być zaimplementowane, aby stał się prostym skryptem do wywołania i może być wywołany przez inny skrypt wsadowo lub cokolwiek innego. Obsługa plików pid dla każdego współbieżnego procesu to problem, który należy rozwiązać, być może użyj innych podkatalogów ...

NB: W systemie GNU Linux sleepmoże przyjmować argumenty zmiennoprzecinkowe, takie jak sleep 0.1spanie przez dziesiątą część sekundy.

Overloaded_Operator
źródło