Ich pdftoppm
möchte ein vom Benutzer bereitgestelltes PDF in ein 300DPI-Bild konvertieren. Dies funktioniert hervorragend, es sei denn, der Benutzer stellt eine PDF-Datei mit einer sehr großen Seitengröße bereit. pdftoppm
reserviert genügend Speicher, um ein 300DPI-Bild dieser Größe im Speicher zu speichern, was für eine 100-Zoll-Quadratseite 100 * 300 * 100 * 300 * 4 Bytes pro Pixel = 3,5 GB entspricht. Ein böswilliger Benutzer könnte mir einfach ein albern großes PDF geben und alle möglichen Probleme verursachen.
Was ich also tun möchte, ist, die Speichernutzung für einen untergeordneten Prozess, den ich ausführen möchte, auf eine harte Grenze zu beschränken. Lassen Sie den Prozess einfach abstürzen, wenn er versucht, mehr als beispielsweise 500 MB Speicher zuzuweisen. Ist das möglich?
Ich glaube nicht, dass ulimit dafür verwendet werden kann, aber gibt es ein Ein-Prozess-Äquivalent?
docker
?Antworten:
Es gibt einige Probleme mit ulimit. Hier finden Sie eine nützliche Lektüre zum Thema: Begrenzen der Zeit und des Speicherverbrauchs eines Programms unter Linux. Dies führt zum Timeout- Tool, mit dem Sie einen Prozess (und seine Forks) nach Zeit und Speicherverbrauch einschränken können.
Das Timeout-Tool erfordert Perl 5+ und das
/proc
bereitgestellte Dateisystem. Danach kopieren Sie das Tool zB/usr/local/bin
so:Danach können Sie Ihren Prozess anhand des Speicherverbrauchs wie in Ihrer Frage wie folgt "einschränken":
Alternativ könnten Sie
-t <seconds>
und ,-x <hertz>
um jeweils den Prozess durch die Zeit oder CPU Einschränkungen zu begrenzen.Die Funktionsweise dieses Tools besteht darin, mehrmals pro Sekunde zu überprüfen, ob der erzeugte Prozess seine festgelegten Grenzen nicht überzeichnet hat. Dies bedeutet, dass es tatsächlich ein kleines Fenster gibt, in dem ein Prozess möglicherweise überzeichnet sein kann, bevor Timeout den Prozess bemerkt und abbricht.
Ein korrekterer Ansatz würde daher wahrscheinlich cgroups beinhalten, aber das Einrichten ist viel aufwendiger, selbst wenn Sie Docker oder runC verwenden, die unter anderem eine benutzerfreundlichere Abstraktion um cgroups bieten.
quelle
coreutils
bezieht! Daher ist die Antwort möglicherweise gefährlich, wenn in einem Paket irgendwo auf Ihrem System ein Skript vorhanden ist,timeout
das als Linux-Standardpaket erwartet wirdcoreutils
! Mir ist nicht bekannt, dass dieses Tool für Distributionen wie Debian gepackt ist.-t <seconds>
Einschränkung den Prozess nach so vielen Sekunden ab?Eine andere Möglichkeit, dies einzuschränken, ist die Verwendung von Linux-Kontrollgruppen. Dies ist besonders nützlich, wenn Sie die Zuordnung des physischen Speichers eines Prozesses (oder einer Gruppe von Prozessen) vom virtuellen Speicher unterscheiden möchten. Zum Beispiel:
erstellt eine Kontrollgruppe mit dem Namen
myGroup
, begrenzt die unter myGroup ausgeführten Prozesse auf bis zu 500 MB physischen Speicher und bis zu 5000 MB Swap. So führen Sie einen Prozess unter der Kontrollgruppe aus:Beachten Sie, dass in einer modernen Ubuntu-Distribution in diesem Beispiel das
cgroup-bin
Paket installiert und bearbeitet werden muss/etc/default/grub
, umGRUB_CMDLINE_LINUX_DEFAULT
zu Folgendem zu wechseln :und dann
sudo update-grub
ausführen und neu starten, um mit den neuen Kernel-Boot-Parametern zu booten.quelle
firejail
Programm können Sie auch einen Prozess mit Speicherbeschränkungen starten (indem Sie cgroups und Namespaces verwenden, um mehr als nur Speicher zu begrenzen). Auf meinen Systemen musste ich die Kernel-Befehlszeile nicht ändern, damit dies funktioniert!GRUB_CMDLINE_LINUX_DEFAULT
Änderung, um die Einstellung dauerhaft zu machen? Ich habe einen anderen Weg gefunden, um es hier hartnäckig zu machen .swapaccount=1
GRUB_CMDLINE_LINUX_DEFAULT?Wenn Ihr Prozess nicht mehr Kinder hervorbringt, die den meisten Speicher verbrauchen, können Sie die
setrlimit
Funktion verwenden. Eine häufigere Benutzeroberfläche dafür ist derulimit
Befehl der Shell:Dies begrenzt nur den "virtuellen" Speicher Ihres Prozesses, wobei berücksichtigt wird - und begrenzt wird -, dass der Speicher, den der aufgerufene Prozess verwendet, mit anderen Prozessen geteilt wird und der Speicher zugeordnet, aber nicht reserviert ist (zum Beispiel der große Heap von Java). Dennoch ist virtueller Speicher die beste Annäherung für Prozesse, die sehr groß werden, wodurch die genannten Fehler unerheblich werden.
Wenn Ihr Programm untergeordnete Elemente erzeugt und sie den Speicher zuweisen, wird es komplexer, und Sie sollten Hilfsskripts schreiben, um Prozesse unter Ihrer Kontrolle auszuführen. Ich habe in meinem Blog geschrieben, warum und wie .
quelle
setrlimit
es für mehr Kinder komplexer?man setrlimit
"Ein über fork (2) erstellterulimit
Ich wollte nur danke sagen - dieser Ansatz hat mir beifirefox
dem Fehler 622816 geholfen - Das Laden eines großen Bildes kann Firefox "einfrieren" oder das System zum Absturz bringen . was bei einem USB-Boot (vom RAM) dazu neigt, das Betriebssystem einzufrieren, was einen harten Neustart erfordert; jetztfirefox
stürzt zumindest selbst ab und lässt das Betriebssystem am Leben ... Prost!Ich verwende das folgende Skript, das funktioniert großartig.
Es werden cgroups through verwendetUpdate: Es werden nun die Befehle von verwendetcgmanager
.cgroup-tools
. Benennen Sie dieses Skriptlimitmem
und fügen Sie es in Ihr $ PATH ein, und Sie können es wie folgt verwendenlimitmem 100M bash
. Dies schränkt sowohl die Speicher- als auch die Auslagerungsnutzung ein. Um nur den Speicher zu begrenzen, entfernen Sie die Zeile mitmemory.memsw.limit_in_bytes
.Bearbeiten: Bei Standard-Linux-Installationen wird dadurch nur die Speichernutzung begrenzt, nicht die Auslagerungsnutzung. Um die Beschränkung der Swap-Nutzung zu aktivieren, müssen Sie die Swap-Abrechnung auf Ihrem Linux-System aktivieren. Tun Sie das , indem Sie / Hinzufügen
swapaccount=1
in/etc/default/grub
so sieht es so etwas wieDann starten
sudo update-grub
und neu starten .Haftungsausschluss: Es würde mich nicht wundern, wenn
cgroup-tools
auch in Zukunft Pausen entstehen. Die richtige Lösung wäre, die systemd-APIs für die Gruppenverwaltung zu verwenden, aber es gibt keine Befehlszeilentools für diese atmquelle
call to cgmanager_create_sync failed: invalid request
für jeden Prozess, mit dem ich versuche zu laufenlimitmem 100M processname
. Ich bin auf Xubuntu 16.04 LTS und das Paket ist installiert.$ limitmem 400M rstudio limiting memory to 400M (cgroup limitmem_24575) for command rstudio Error org.freedesktop.DBus.Error.InvalidArgs: invalid request
Irgendeine Idee?percent
Null ergibt,expr
lautet der Statuscode 1, und dieses Skript wird vorzeitig beendet. empfehle die Zeile zu ändern:percent=$(( "$peak_mem" / $(( "$bytes_limit" / 100 )) ))
(ref: unix.stackexchange.com/questions/63166/… )Zusätzlich zu den
daemontools
von Mark Johnson vorgeschlagenen Tools von können Sie auch berücksichtigen,chpst
welche in enthalten sindrunit
. Runit selbst ist im Lieferumfang enthaltenbusybox
, sodass es möglicherweise bereits installiert ist.Die Manpage von
chpst
zeigt die Option:quelle
Ich verwende Ubuntu 18.04.2 LTS und das JanKanis-Skript funktioniert nicht ganz so, wie er es vorschlägt. Laufen
limitmem 100M script
ist die Begrenzung von 100 MB RAM mit unbegrenztem Swap.Die Ausführung
limitmem 100M -s 100M script
schlägt unbemerkt fehl, dacgget -g "memory:$cgname"
kein Parameter angegeben wurdememory.memsw.limit_in_bytes
.Also habe ich Swap deaktiviert:
quelle
Auf jeder systemd-basierten Distribution können Sie cgroups auch indirekt über systemd-run verwenden.
pdftoppm
Verwenden Sie beispielsweise für den Fall einer Beschränkung auf 500 MB RAM Folgendes:Hinweis: Hier werden Sie nach einem Passwort gefragt, aber die App wird als Ihr Benutzer gestartet. Lassen Sie sich nicht täuschen, dass der Befehl benötigt wird
sudo
, da der Befehl dann unter root ausgeführt wird, was kaum Ihre Absicht war.Wenn Sie das Passwort nicht eingeben möchten (schließlich benötigen Sie als Benutzer, dessen Speicher Sie besitzen, ein Passwort, um es
--user
einzuschränken ) , können Sie die Option verwenden. Damit dies funktioniert, muss jedoch die Unterstützung von cgroupsv2 aktiviert sein Jetzt muss mit demsystemd.unified_cgroup_hierarchy
Kernel-Parameter gebootet werden .quelle