Automatycznie zabij proces, jeśli przekroczy on określoną ilość pamięci RAM

13

Pracuję na dużych zbiorach danych. Podczas testowania nowego oprogramowania skrypt czasami się do mnie podkrada, szybko chwyta całą dostępną pamięć RAM i sprawia, że ​​mój komputer nie nadaje się do użytku. Chciałbym, aby ustawić limit pamięci RAM dla procesu, aby jeśli przekroczyłby tę ilość, zostanie automatycznie zabity. Rozwiązanie specyficzne dla języka prawdopodobnie nie będzie działać, ponieważ używam różnego rodzaju różnych narzędzi (R, Perl, Python, Bash itp.).

Czy istnieje jakiś monitor procesu, który pozwoli mi ustawić próg ilości pamięci RAM i automatycznie zabić proces, jeśli zużyje więcej?

chrisamiller
źródło
@ Uri: W tym wątku mam tylko częściową (tylko dla części procesora mojego pytania) - i nie optymalną - odpowiedź. Pyta o wykorzystanie pamięci RAM.
Chriskin
1
Uri, w tym wątku jest kompletny brak przydatnych pomysłów. Publikowanie linku do niego nie jest szczególnie pomocne.
chrisamiller
1
Hrmm - ten wątek superuser wydaje się mieć rozsądną sugestię korzystania ulimit: superuser.com/questions/66383/restrict-ram-for-user-or-process
chrisamiller

Odpowiedzi:

11

Nienawidzę być facetem, który odpowiada na swoje własne pytanie, ale dziś rano znalazłem alternatywną metodę, zapakowaną w miłe, małe narzędzie. Ograniczy czas pracy procesora lub zużycie pamięci:

https://github.com/pshved/timeout

Najpierw daję temu szansę, ale głosuję za Amey Jah za miłą odpowiedź. Sprawdzę, czy to mnie zawiodło.

chrisamiller
źródło
5
+1 Odpowiedź na własne pytanie jest OK !
Tom Brossman,
10

Zdecydowanie odradzam to robić . Jak sugeruje @chrisamiller, ustawienie ulimit ograniczy pamięć RAM dostępną w procesie.

Ale jeśli nalegasz, postępuj zgodnie z tą procedurą.

  1. Zapisz następujący skrypt jako killif.sh:

    #!/bin/sh
    
    if [ $# -ne 2 ];
    then
        echo "Invalid number of arguments"
        exit 0
    fi
    
    while true;
    do
        SIZE=$(pmap $1|grep total|grep -o "[0-9]*")
        SIZE=${SIZE%%K*}
        SIZEMB=$((SIZE/1024))
        echo "Process id =$1 Size = $SIZEMB MB"
        if [ $SIZEMB -gt $2 ]; then
            printf "SIZE has exceeded.\nKilling the process......"
            kill -9 "$1"
            echo "Killed the process"
            exit 0
        else
            echo "SIZE has not yet exceeding"
        fi
    
        sleep 10
    done
  2. Teraz spraw, by był wykonywalny.

    chmod +x killif.sh
    
  3. Teraz uruchom ten skrypt na terminalu. Zamień na PROCIDrzeczywisty identyfikator procesu i SIZErozmiar w MB.

    ./killif.sh PROCID SIZE
    

    Na przykład:

    ./killif.sh 132451 100
    

    Jeśli SIZEwynosi 100, proces zostanie zabity, jeśli jego użycie pamięci RAM wzrośnie powyżej 100 MB.

Uwaga: wiesz, co próbujesz zrobić. Proces zabijania nie jest dobrym pomysłem. Jeśli w tym procesie jest komenda zamknięcia lub zatrzymania, edytuj skrypt i zastąp kill -9komendę tą shutdownkomendą.

Amey Jah
źródło
rozważyłbym trochę snu, na przykład sen 0,5 ...
Denwerko
@George Edison Jak to zrobiłeś. Kiedy próbowałem wkleić, dawał mi dziwnie sformatowany tekst. Denwerko: Gdzie chciałbyś spać. Położyłem już 10 sekund na sen w pętli while
Amey Jah,
2
Dzięki za rozwiązanie, jak wspomniano poniżej, mogę to sprawdzić. Dlaczego jednak wszystkie straszne ostrzeżenia o procesach zabijania? Oprogramowanie do zarządzania klastrami (LSF, PBS i in.) Robi to cały czas, gdy proces przekracza ilość wymaganych zasobów, bez żadnych poważnych konsekwencji. Zgadzam się, że nie jest to dobre rozwiązanie dla nowych użytkowników, którzy mogą go źle zastosować, ale w odpowiednich okolicznościach może to być bardzo przydatne.
chrisamiller
@chrisamiller Ustawiłem ostrzeżenie dla przyszłych czytelników. W twoim przypadku znasz implikacje, ale przyszły czytelnik tego postu może nie być świadomy takich implikacji.
Amey Jah,
2
Czy możesz wyjaśnić, dlaczego tego nie zrobić?
jterm
2

Wypróbuj prlimitnarzędzie z util-linuxpakietu. Działa program z limitami zasobów. Używa prlimitwywołania systemowego do ustawiania limitów, które są następnie wymuszane wyłącznie przez jądro.

Możesz skonfigurować 16 limitów, w tym:

  • maksymalny czas procesora w sekundach
  • maksymalna liczba procesów użytkownika
  • maksymalny ustawiony rozmiar rezydenta („używana pamięć”)
  • maksymalny rozmiar, jaki proces może zablokować w pamięci
  • rozmiar pamięci wirtualnej
  • maksymalna liczba otwartych plików
  • maksymalna liczba blokad plików
  • maksymalna liczba oczekujących sygnałów
  • maksymalna liczba bajtów w kolejkach komunikatów POSIX
Bram Geron
źródło
0

To było zbyt duże, aby zmieściło się w komentarzu. Zmodyfikowałem oryginalny skrypt Ameya, aby zawierał a pgrep, więc zamiast ręcznie wpisywać identyfikator procesu, możesz po prostu wykluczyć według nazwy. Na przykład ./killIf.sh chrome 4000zabija każdy proces chrome, który przekracza 4 GB pamięci.

#!/bin/sh

# $1 is process name
# $2 is memory limit in MB

if [ $# -ne 2 ];
then
    echo "Invalid number of arguments"
    exit 0
fi

while true;
do
    pgrep "$1" | while read -r procId;
    do
        SIZE=$(pmap $procId | grep total | grep -o "[0-9]*")
        SIZE=${SIZE%%K*}
        SIZEMB=$((SIZE/1024))
        echo "Process id = $procId Size = $SIZEMB MB"
        if [ $SIZEMB -gt $2 ]; then
            printf "SIZE has exceeded.\nKilling the process......"
            kill -9 "$procId"
            echo "Killed the process"
            exit 0
        else
            echo "SIZE has not yet exceeding"
        fi
    done

    sleep 1
done

Uważaj, aby wybrać wąski ciąg grep i wystarczająco duży limit pamięci, aby niepotrzebnie nie zabijać niezamierzonych procesów.

Gaurang Tandon
źródło