So begrenzen Sie die Gesamtressourcen (Speicher) eines Prozesses und seiner untergeordneten Elemente

16

Es gibt viele Fragen und Antworten zum Einschränken der Ressourcen eines einzelnen Prozesses, z. B. kann RLIMIT_AS verwendet werden, um den durch einen Prozess zugewiesenen maximalen Speicher einzuschränken, der in etwa als VIRT angesehen werden kann top. Mehr zum Thema zB hier Gibt es eine Möglichkeit, die Speicherkapazität zu begrenzen, die ein bestimmter Prozess in Unix verwenden kann?

setrlimit(2) Dokumentation sagt:

Ein über fork (2) erstellter untergeordneter Prozess erbt die Ressourcenbeschränkungen des übergeordneten Prozesses. Ressourcenlimits werden in execve (2) beibehalten.

Es sollte folgendermaßen verstanden werden:

Wenn ein Prozess ein RLIMIT_AS von z. B. 2 GB hat, kann er nicht mehr Speicher als 2 GB zuweisen. Wenn ein untergeordnetes Element erzeugt wird, wird das Adressraumlimit von 2 GB an das untergeordnete Element weitergegeben, die Zählung beginnt jedoch bei 0. Die beiden Prozesse zusammen können bis zu 4 GB Speicher belegen.

Aber wie könnte man die Gesamtsumme des von einem ganzen Prozessbaum zugewiesenen Speichers begrenzen?

jpe
quelle
7
Ich würde einen Blick auf cgroups werfen .
SLM
@slm Danke! Klingt wie Cgroups ist etwas zu versuchen. Die einzige funktionierende Lösung, die bis jetzt funktioniert (abgesehen von einer hässlichen Art, den Speicher mit PS zu summieren und den übergeordneten Prozess zu beenden, wenn die Obergrenze überschritten wird), ist die Verwendung einer Art Container (lxc oder ähnliches).
jpe
Ja - die Tools, die mir bekannt sind, führen keine Gruppen durch, sondern nur einzelne Prozesse. Angesichts der Funktionsweise von Cgroups für VM-Technologien wie LXC und Docker würde ich davon ausgehen, dass sie das tun, was Sie wollen.
slm
1
Wenn es sich um Linux handelt, geben Sie die übergeordnete PID in einen eigenen Namespace ein und steuern Sie sie und alle untergeordneten PIDs auf diese Weise. Hier ist eine einleitende Antwort auf dieses Konzept: unix.stackexchange.com/a/124194/52934
mikeserv

Antworten:

8

Ich bin nicht sicher, ob dies Ihre Frage beantwortet, aber ich habe dieses Perl-Skript gefunden , das behauptet, genau das zu tun, wonach Sie suchen. Das Skript implementiert ein eigenes System zur Durchsetzung der Grenzwerte, indem es die Ressourcennutzung des Prozesses und seiner untergeordneten Elemente aufweckt und überprüft. Es scheint gut dokumentiert und erklärt zu sein und wurde kürzlich aktualisiert.

Wie slm in seinem Kommentar sagte, können dafür auch cgroups verwendet werden. Möglicherweise müssen Sie die Dienstprogramme zum Verwalten von Gruppen installieren, vorausgesetzt, Sie arbeiten unter Linux, nach denen Sie suchen sollten libcgroups.

sudo cgcreate -t $USER:$USER -a $USER:$USER -g memory:myGroup

Stellen Sie sicher, dass $USERes sich um Ihren Benutzer handelt.

Ihr Benutzer sollte dann Zugriff auf die Einstellungen des Arbeitsspeichers in haben /sys/fs/cgroup/memory/myGroup.

Sie können dann das Limit auf beispielsweise 500 MB setzen, indem Sie dies tun:

echo 500000000 > /sys/fs/cgroup/memory/myGroup/memory.limit_in_bytes

Lass uns nun Vim starten:

cgexec -g memory:myGroup vim

Der vim-Prozess und alle seine untergeordneten Elemente sollten jetzt auf 500 MB RAM beschränkt sein. Ich denke jedoch , dass dieses Limit nur für RAM gilt und nicht für Swap. Sobald die Prozesse das Limit erreichen, beginnen sie zu tauschen. Ich bin mir nicht sicher, ob Sie dies umgehen können. Ich kann keine Möglichkeit finden, die Swap-Nutzung mithilfe von cgroups einzuschränken.

Arnefm
quelle
Die vorgeschlagene Lösung ermöglicht es, die Größe der residenten Gruppe eines Prozessbaums zu begrenzen. Das Verhalten scheint sich von RLIMIT_AS zu unterscheiden: Es ist möglich, mehr Speicher als das Limit zuzuordnen, es scheint jedoch nicht möglich zu sein, tatsächlich mehr zu verwenden.
jpe
Standardmäßig gilt das Speicherlimit für Gruppen nur (ungefähr) für die physische RAM-Nutzung. Es gibt eine Kernel-Option (CONFIG_MEMCG_SWAP), um die Swap-Abrechnung zu aktivieren. Einzelheiten finden Sie in den Kernel-Dokumenten .
Søren Løvborg,
1
Am Fedora,sudo yum install libcgroup-tools
Jozxyqk
2

Ich habe mit cgmanager, das in Ubuntu verwendet wird, ein Skript erstellt, das dies ausführt. Ein Vorteil ist, dass hierfür kein Root-Zugriff erforderlich ist. Beachten Sie, dass die Gruppenverwaltung etwas distro-spezifisch ist, sodass ich nicht weiß, ob dies auf Distributionen funktioniert, die die systemd-Gruppenverwaltung verwenden.

#!/bin/sh

set -eu

if [ "$#" -lt 2 ]
then
    echo Usage: `basename $0` "<limit> <command>..."
    exit 1
fi

limit="$1"
shift
cgname="limitmem_$$"
echo "limiting memory to $limit (cgroup $cgname) for command $@"

cgm create memory "$cgname" >/dev/null
cgm setvalue memory "$cgname" memory.limit_in_bytes "$limit" >/dev/null
# try also limiting swap usage, but this fails if the system has no swap
cgm setvalue memory "$cgname" memsw.limit_in_bytes "$limit" >/dev/null 2>&1 || true

# spawn subshell to run in the cgroup
set +e
(
set -e
cgm movepid memory "$cgname" `sh -c 'echo $PPID'` > /dev/null
exec "$@"
)
# grab exit code
exitcode=`echo $?`

set -e

echo -n "peak memory used: "
cgm getvalue memory "$cgname" memory.max_usage_in_bytes | tail -1 | cut -f2 -d\"

cgm remove memory "$cgname" >/dev/null
exit $exitcode

Verwendung: Speichern Sie es unter limitmemIhrem Pfad und machen Sie es ausführbar. Dann laufen zB limitmem 1G command.... Dies begrenzt den tatsächlich verwendeten Speicher. Wenn dies erreicht ist, bricht der OOM-Killer den Prozess oder eines seiner Kinder ab, aber nicht etwas Zufälliges, das nichts mit diesem Befehl zu tun hat.

JanKanis
quelle
Vielen Dank für die kurze cgmAnleitung, es war nützlich
Vitaly Isaev
1

/unix//a/536046/4319 :

Auf jeder systemd-basierten Distribution können Sie cgroups auch indirekt über systemd-run verwenden. pdftoppmVerwenden Sie beispielsweise für den Fall der Beschränkung auf 500 MB RAM Folgendes:

systemd-run --scope -p MemoryLimit=500M pdftoppm

...

imz - Ivan Zakharyaschev
quelle