Pracuję, pdftoppm
aby przekonwertować plik PDF dostarczony przez użytkownika na obraz 300DPI. Działa to świetnie, z wyjątkiem sytuacji, gdy użytkownik dostarczy plik PDF o bardzo dużym rozmiarze strony. pdftoppm
przydzieli wystarczającą ilość pamięci, aby pomieścić obraz 300DPI o takim rozmiarze w pamięci, który dla strony o przekątnej 100 cali wynosi 100 * 300 * 100 * 300 * 4 bajtów na piksel = 3,5 GB. Złośliwy użytkownik może po prostu dać mi głupio duży plik PDF i powodować różnego rodzaju problemy.
Chciałbym więc ustalić jakiś twardy limit wykorzystania pamięci dla procesu potomnego, który zamierzam uruchomić - po prostu umieść proces, jeśli spróbuje przydzielić więcej niż, powiedzmy, 500 MB pamięci. Czy to jest możliwe?
Nie sądzę, że można do tego użyć ulimit, ale czy istnieje odpowiednik jednego procesu?
docker
?Odpowiedzi:
Istnieją pewne problemy z ulimit. Oto przydatna lektura na ten temat: Ograniczanie czasu i zużycia pamięci przez program w systemie Linux , co prowadzi do narzędzia do limitowania czasu , które pozwala na umieszczenie procesu (i jego rozwidleń) w klatkach według zużycia czasu lub pamięci.
Narzędzie do przekroczenia limitu czasu wymaga Perla 5+ i podłączonego
/proc
systemu plików. Następnie skopiuj narzędzie, aby np./usr/local/bin
Tak:Następnie możesz „zablokować” proces według zużycia pamięci, tak jak w pytaniu:
Alternatywnie możesz użyć
-t <seconds>
i-x <hertz>
odpowiednio ograniczyć proces przez ograniczenia czasowe lub procesorowe.To narzędzie działa, sprawdzając wiele razy na sekundę, czy odrodzony proces nie przekroczył swoich ustawionych granic. Oznacza to, że w rzeczywistości jest małe okno, w którym proces może potencjalnie nadmiernie subskrybować, zanim przekroczą limit czasu i zakończy proces.
Bardziej poprawne podejście prawdopodobnie dotyczyłoby grup, ale jest to o wiele bardziej zaangażowane w konfigurację, nawet jeśli użyjesz Dockera lub RunC, które między innymi oferują bardziej przyjazną dla użytkownika abstrakcję wokół grup.
źródło
coreutils
narzędzia linux o tej samej nazwie! Tak więc odpowiedź jest potencjalnie niebezpieczna, jeśli gdziekolwiek w twoim systemie, jakiś pakiet ma skrypt, który spodziewatimeout
się być standardowymcoreutils
pakietem linux ! Nie wiem, czy to narzędzie jest pakowane do dystrybucji takich jak debian.-t <seconds>
ograniczenie zabija proces po tak wielu sekundach?Innym sposobem ograniczenia tego jest użycie grup kontrolnych Linuksa. Jest to szczególnie przydatne, jeśli chcesz ograniczyć alokację pamięci fizycznej procesu (lub grupy procesów) w odróżnieniu od pamięci wirtualnej. Na przykład:
utworzy grupę kontrolną o nazwie
myGroup
, ograniczy zestaw procesów uruchomionych w ramach mojej grupy do 500 MB pamięci fizycznej i do 5000 MB wymiany. Aby uruchomić proces w grupie kontrolnej:Pamiętaj, że w nowoczesnej dystrybucji Ubuntu ten przykład wymaga zainstalowania
cgroup-bin
pakietu i edycji,/etc/default/grub
aby zmienićGRUB_CMDLINE_LINUX_DEFAULT
na:a następnie uruchomienie
sudo update-grub
i ponowne uruchomienie w celu uruchomienia z nowymi parametrami rozruchowymi jądra.źródło
firejail
Program pozwala także rozpocząć proces limitów pamięci (używając cgroups i nazw ograniczyć więcej niż tylko pamięć). W moich systemach nie musiałem zmieniać wiersza poleceń jądra, aby to działało!GRUB_CMDLINE_LINUX_DEFAULT
modyfikacji, aby ustawienie było trwałe? Znalazłem tutaj inny sposób, aby upierać się przy tym .swapaccount=1
w GRUB_CMDLINE_LINUX_DEFAULT?Jeśli twój proces nie odrodzi więcej dzieci, które zużywają najwięcej pamięci, możesz użyć
setrlimit
funkcji. Bardziej powszechnym interfejsem użytkownika jest użycieulimit
polecenia powłoki:Ograniczy to tylko „wirtualną” pamięć twojego procesu, biorąc pod uwagę - i ograniczając - pamięć wywoływanego procesu współużytkuje z innymi procesami oraz pamięć mapowaną, ale niezastrzeżoną (na przykład dużą stertę Javy). Mimo to pamięć wirtualna jest najbliższym przybliżeniem procesów, które stają się naprawdę duże, przez co wspomniane błędy są nieistotne.
Jeśli twój program odradza dzieci i to one przydzielają pamięć, staje się bardziej złożony i powinieneś pisać skrypty pomocnicze, aby uruchamiać procesy pod kontrolą. Napisałem na moim blogu, dlaczego i jak .
źródło
setrlimit
bardziej złożony dla większej liczby dzieci?man setrlimit
mówi mi, że „Proces potomny utworzony za pomocą fork (2) dziedziczy limity zasobów nadrzędnych. Limity zasobów są zachowane w execve (2)”ulimit
podejście pomogło mifirefox
„s bug 622816 - Loading dużego obrazu można«zamrozić»Firefox, lub awarii systemu ; który przy rozruchu USB (z pamięci RAM) ma tendencję do zawieszania systemu operacyjnego, wymagając twardego restartu; teraz przynajmniejfirefox
ulega awarii, pozostawiając system operacyjny przy życiu ... Pozdrawiam!Korzystam z poniższego skryptu, który działa świetnie.
Używa cgroups przezAktualizacja: teraz używa poleceń zcgmanager
.cgroup-tools
. Nazwij ten skryptlimitmem
i umieść go w $ PATH, a będziesz mógł go używać tak jaklimitmem 100M bash
. Ograniczy to wykorzystanie pamięci i wymiany. Aby ograniczyć tylko pamięć, usuń linię za pomocąmemory.memsw.limit_in_bytes
.edycja: W domyślnych instalacjach Linuksa ogranicza to tylko użycie pamięci, a nie zamianę. Aby włączyć ograniczenie użycia wymiany, należy włączyć rozliczanie wymiany w systemie Linux. To zrobić poprzez ustawienie / dodanie
swapaccount=1
w/etc/default/grub
tak to wygląda mniej więcej takNastępnie uruchom
sudo update-grub
i uruchom ponownie.Oświadczenie: Nie zdziwiłbym się, gdyby
cgroup-tools
również przerwy w przyszłości. Prawidłowym rozwiązaniem byłoby użycie systemd API do zarządzania grupami, ale dla tego bankomatu nie ma narzędzi wiersza poleceńźródło
call to cgmanager_create_sync failed: invalid request
dla każdego procesu, z którym staram się biegaćlimitmem 100M processname
. Jestem na Xubuntu 16.04 LTS i ten pakiet jest zainstalowany.$ limitmem 400M rstudio limiting memory to 400M (cgroup limitmem_24575) for command rstudio Error org.freedesktop.DBus.Error.InvalidArgs: invalid request
jakiś pomysł?percent
wyniku są zerowe,expr
kod stanu wynosi 1, a ten skrypt kończy się przedwcześnie. polecam zmianę linii na:percent=$(( "$peak_mem" / $(( "$bytes_limit" / 100 )) ))
(ref: unix.stackexchange.com/questions/63166/… )Oprócz narzędzi z
daemontools
, sugerowanych przez Marka Johnsona, możesz również rozważyć,chpst
które z nich można znaleźćrunit
. Samo Runit jest dołączonebusybox
, więc możesz już go zainstalować.Strona człowiek
chpst
pokazuje opcję:źródło
Korzystam z systemu Ubuntu 18.04.2 LTS, a skrypt JanKanis nie działa dla mnie tak, jak sugeruje. Bieganie
limitmem 100M script
ogranicza 100 MB pamięci RAM przy nieograniczonej zamianie.Uruchamianie
limitmem 100M -s 100M script
kończy się bezgłośnie, ponieważcgget -g "memory:$cgname"
nie ma określonego parametrumemory.memsw.limit_in_bytes
.Więc wyłączyłem zamianę:
źródło
W każdej dystrybucji opartej na systemie możesz także używać grup pośrednio przez systemd-run. Na przykład w przypadku ograniczenia
pdftoppm
do 500 MB pamięci RAM użyj:Uwaga: poprosi Cię o podanie hasła, ale aplikacja zostanie uruchomiona jako użytkownik. Nie daj się zwieść myśleniu, że polecenie to potrzebuje
sudo
, ponieważ spowodowałoby to uruchomienie komendy pod rootem, co nie było twoim zamiarem.Jeśli nie chcesz wpisywać hasła (w końcu, jako użytkownik posiadasz pamięć, dlaczego potrzebujesz hasła, aby ją ograniczyć) , możesz użyć
--user
opcji, jednak aby to zadziałało, musisz włączyć obsługę cgroupsv2, które to prawo teraz wymaga uruchomienia zsystemd.unified_cgroup_hierarchy
parametrem jądra .źródło