Das Begrenzen von Prozessen auf maximal 10% der CPU-Auslastung

32

Ich betreibe ein Linux-System, das viele Benutzer hat, aber manchmal tritt ein Missbrauch auf. Hier kann ein Benutzer einen einzelnen Prozess ausführen, der mehr als 80% der CPU / des Speichers beansprucht.

Gibt es eine Möglichkeit, dies zu verhindern, indem die CPU-Auslastung, die ein Prozess verbrauchen kann (beispielsweise auf 10%)? Mir ist bekannt cpulimit, aber leider werden die von mir angewiesenen Prozesse begrenzt (z. B. einzelne Prozesse). Meine Frage ist also, wie ich das Limit auf alle laufenden Prozesse und Prozesse anwenden kann, die in Zukunft ausgeführt werden, ohne dass beispielsweise die ID / der Pfad angegeben werden muss.

Giovanni Mounir
quelle
Haben Sie Leistungsprobleme? oder stören dich nur die zahlen
Strg-Alt-Delor
@richard Performance-Probleme, deshalb habe ich versucht, Prozesse, die viel CPU zu verbrauchen scheinen, zu beenden, aber ich habe dies bereits getan, indem ich ein Bash-Skript geschrieben habe. Dies ist auch eine virtuelle Maschine, wenn das hilft
Giovanni Mounir
2
Seien Sie vorsichtig, wenn Sie Prozesse beenden, die für sehr kurze Zeit zu 100% sein können, auch Systemprozesse. Betrachten Sie cpulimitin Verbindung mit Ihrem Suchskript. Haben Sie eine Richtlinie und empfehlen Sie die Verwendung von cpulimit, suchen Sie dann nach über 10% und beschränken Sie sich dann auf 5% (daher werden Benutzer zur Verwendung aufgefordert cpulimit). Stellen Sie außerdem sicher, dass Sie mehrere Prozesse erkennen können, die für einen einzelnen Benutzer mehr als 10% betragen.
Strg-Alt-Delor
@richard Danke Richard für all diese nützlichen Kommentare! Sie haben mir sehr geholfen! Ihr Vorschlag cpulimitist viel besser als nur das Beenden des Prozesses, da er später vom Benutzer neu gestartet werden kann (wie in einem Ihrer Kommentare angegeben). Vielen Dank!
Giovanni Mounir
1
stackoverflow.com/questions/386945/…
Ciro Santilli Mitglied seit

Antworten:

20

Während es ein Missbrauch für den Speicher sein kann, ist es nicht für die CPU: Wenn eine CPU im Leerlauf ist, dauert ein laufender Prozess (durch "Laufen" meine ich, dass der Prozess nicht auf E / A oder etwas anderes wartet) Standardmäßig 100% CPU-Zeit. Und es gibt keinen Grund, ein Limit durchzusetzen.

Jetzt können Sie dank Prioritäten setzen nice. Wenn Sie möchten, dass sie auf alle Prozesse für einen bestimmten Benutzer angewendet werden, müssen Sie nur sicherstellen, dass seine Anmeldeshell mit ausgeführt wird nice: Die untergeordneten Prozesse erben den niceWert. Dies hängt davon ab, wie sich die Benutzer anmelden. Siehe z. B. Priorisieren von SSH-Anmeldungen (nett) .

Alternativ können Sie virtuelle Maschinen einrichten. In der Tat ist das Festlegen eines Limits pro Prozess wenig sinnvoll, da der Benutzer viele Prozesse starten kann, wodurch das System missbraucht wird. Bei einer virtuellen Maschine sind alle Beschränkungen für die virtuelle Maschine global.

Eine andere Lösung besteht darin, /etc/security/limits.confGrenzen zu setzen . Siehe die Manpage limits.conf (5). Beispielsweise können Sie die maximale CPU-Zeit pro Anmeldung und / oder die maximale Anzahl von Prozessen pro Anmeldung festlegen. Sie können auch maxloginsfür jeden Benutzer den Wert 1 festlegen .

vinc17
quelle
1
@GiovanniMounir Ich meinte: eine virtuelle Maschine pro Benutzer.
Vinc17
1
Ich verstehe, aber leider ist dies ressourcenaufwendig und für meinen Zweck nicht wirklich nützlich, da die Benutzer möglicherweise die Verwendung einiger allgemeiner Entwicklungspakete benötigen und ich dies nicht auf jedem einzelnen neuen Computer installieren werde. Ich denke, es ist besser, dies so zu belassen und die Überwachung automatisch durch ein Bash-Skript durchzuführen.
Giovanni Mounir
1
@GiovanniMounir Sie können eine Partition für mehrere virtuelle Maschinen freigeben.
Vinc17
@GiovanniMounir Mit LXC oder Docker können Sie den Virtualisierungsaufwand auf nahezu null reduzieren. Auch "Liken" ist kein starker Grund. Zum Beispiel würde ich mich für Ihre Lösung entscheiden, wenn Sie einen gemeinsam genutzten PHP-Host verwalten, da für LXCs oder virtuelle Maschinen eine Lizenzsoftware im Wert von 15 USD / 5 USD neu geschrieben werden muss.
Pooyan Khosravi
Ich verstehe, dass nice nur die relative CPU im Vergleich zu anderen Prozessen einstellt. Wenn kein anderer Prozess CPU verwendet, verwendet Ihr Prozess 100% CPU und ist nicht auf 10% beschränkt.
Johny, warum
25

nett / renice

nice ist ein großartiges Tool für einmalige Optimierungen an einem System.

 nice COMMAND

cpulimit

cpulimit Wenn Sie einen CPU-intensiven Job ausführen und freie CPU-Zeit benötigen, ist dies für die Reaktionsfähigkeit eines Systems von entscheidender Bedeutung.

cpulimit -l 50 COMMAND

cgroups

cgroups Grenzen nicht nur für einen, sondern für eine Reihe von Prozessen festlegen

cgcreate -g cpu:/cpulimited
cgset -r cpu.shares=512 cpulimited
cgexec -g cpu:cpulimited COMMAND_1
cgexec -g cpu:cpulimited COMMAND_2
cgexec -g cpu:cpulimited COMMAND_3

Ressourcen

http://blog.scoutapp.com/articles/2014/11/04/restricting-process-cpu-usage-using-nice-cpulimit-and-cgroups

RafaSashi
quelle
5
Für diejenigen, die eine harte Begrenzung der CPU-Auslastung festlegen möchten, auch wenn kein anderer Prozess ausgeführt wird, cpu.cfs_quota_ussiehe Parameter (siehe Handbuch )
Diego,
cgroups sind dank systemd-anweisungen einfacher zu bedienen ... erstellen sie eine einheit entweder system oder benutzer für diesen zweck ist die beste option
Yves Martin
für einen laufenden Prozess zB:sudo cgclassify -g cpu:cpulimited 2315444
Aquarius Power
1
Ich verstehe, dass nice nur die relative CPU im Vergleich zu anderen Prozessen einstellt. Wenn kein anderer Prozess CPU verwendet, verwendet Ihr Prozess 100% CPU und ist nicht auf 10% beschränkt.
Johny, warum
10

Hast du dir cgroups angesehen? Es gibt einige Informationen im Arch Wiki darüber. Lesen Sie den Abschnitt darüber cpu.shares, es sieht so aus, als ob es das tut, was Sie brauchen, und sie können auf Benutzerebene arbeiten, so dass Sie alle Benutzerprozesse auf einmal begrenzen können.

Paul Schyska
quelle
CGroups ist der richtige Weg. Ich verwende auch (viele) gemeinsam genutzte Computerserver und wir verwenden cgroups, um die maximale Anzahl von Kernen zu begrenzen, die eine gesamte Anmeldesitzung verwenden kann. Auf diese Weise erhält jede Person eine kleinere Scheibe, wenn sie immer wieder neue Prozesse startet. Gleiches gilt für die Speichernutzung. Sie können Benutzer mit pam_cgroups und dem cgrulesengd-Dienst automatisch in eine cgroup einfügen lassen. Sie können eine 'Vorlage' in der cgconfig-Datei verwenden, um jeden Benutzer in eine eigene cgroup zu setzen. cgrulesengd verhält sich wie Ihr Skript, außer dass es Prozesse nicht beendet, sondern nur sicherstellt, dass sich jeder Prozess in der richtigen cgroup befindet.
Jsbillings
Auch wenn Sie die Ressourcennutzung nicht mit cgroups einschränken , können Sie damit auswerten, wie viele Ressourcen eine Person verwendet, indem Sie sich die 'stat'-Datei für jede Ressource ansehen und diese Informationen für Ihr 5-Minuten-Skript verwenden.
Jsbillings
3

Nach Erinnerung suchen Sie ulimit -v. Beachten Sie, dass dies ulimitvon untergeordneten Prozessen geerbt wird. Wenn Sie es also zum Zeitpunkt der Anmeldung auf die Anmeldeshell des Benutzers anwenden, gilt es für alle seine Prozesse.

Wenn Ihre Benutzer alle bashals Login-Shell verwenden, /etc/profilesollte die Eingabe der folgenden Zeile dazu führen, dass für alle Benutzerprozesse ein festes Limit von 1 Gigabyte (genauer gesagt eine Million Kilobyte) festgelegt ist:

ulimit -vH 1000000

Die Option Hstellt sicher, dass es sich um ein hartes Limit handelt, das heißt, der Benutzer kann es anschließend nicht mehr wiederherstellen. Natürlich kann der Benutzer den Speicher immer noch füllen, indem er ausreichend viele Prozesse gleichzeitig startet.

Für andere Shells müssen Sie herausfinden, welche Initialisierungsdateien sie stattdessen lesen (und welchen anderen Befehl ulimitsie verwenden).

Was Sie sich für die CPU wünschen, scheint für mich keinen Sinn zu ergeben. Was nützt es, wenn 90% der CPU ungenutzt bleiben, wenn nur ein Prozess ausgeführt wird? Ich denke, was Sie wirklich wollen, ist nice(und möglicherweise ionice). Beachten Sie, dass, wie ulimit, nicesind Werte , die von untergeordneten Prozessen geerbt, so dass es auf den Login - Shell bei der Anmeldung genügt die Anwendung. Ich denke, das trifft auch zu ionice, bin mir aber nicht sicher.

Celtschk
quelle
Danke für den Erinnerungsvorschlag! Gibt es eine Möglichkeit, mir ein Beispiel zu zeigen, um dies zum Zeitpunkt der Anmeldung auf die Anmeldeshell des Benutzers anzuwenden? Ich bin mir nicht sicher, wie ich das machen soll. Es tut mir auch leid, dass ich nicht klar genug bin. Was ich versuche, ist, dass kein Prozess mehr als 10% der CPU auslastet. Glaubst du, das nicewird nett genug sein, um das zu tun? Wenn ja, können Sie mir ein Beispiel zeigen, um dies zu erreichen?
Giovanni Mounir
Ich verstehe es immer noch nicht, die CPU zu 90% im Leerlauf zu halten, wenn nur ein Prozess ausgeführt wird.
Celtschk
1
Wenn derzeit weniger als 10 Prozesse gleichzeitig ausgeführt werden (und damit meine ich, dass sie tatsächlich ausgeführt werden und nicht nur auf Benutzereingaben oder Festplatten-E / A warten), ist praktisch garantiert, dass einer von ihnen mehr als 10% der CPU hat. Andernfalls würde die CPU praktisch im Leerlauf sein. Und wenn Sie nur einen Prozess beenden, der über 10% hinausgeht, werden Sie sicher viele Benutzer haben, die Sie beenden möchten . Oder werde zumindest versuchen, dich durch jemanden zu ersetzen, der eine Ahnung hat, was diese Zahlen bedeuten, weil du es scheinbar nicht tust.
Celtschk
Im Gegensatz zu @celtschks Kommentar werden bei 11 oder mehr laufenden Prozessen (CPU-gebunden) weniger als 9,09% ausgeführt. Wenn ich also ein Benutzer eines Systems bin, das eine CPU-Auslastung von mehr als 10% verbietet, kann ich 11 oder mehr Prozesse ausführen und mich unter dem Radar verstecken.
Strg-Alt-Delor
@richard Sie haben Recht, vielleicht ist es besser, wenn das Skript die Gesamtmenge des von einem Benutzer verwendeten Speichers / der CPU aufsummiert und dann alle Prozesse dieses Benutzers beendet, wenn der Prozentsatz eine bestimmte Menge erreicht (also ihn auch protokolliert) out)
Giovanni Mounir
3

Da Sie angeben, dass cpulimit in Ihrem Fall nicht praktikabel wäre, schlage ich vor, Sie betrachten nice , renice und taskset , die möglicherweise dem nahe kommen, was Sie erreichen möchten, obwohl taskset das Festlegen der CPU-Affinität eines Prozesses ermöglicht ist in Ihrem Fall möglicherweise nicht sofort hilfreich.

RJ
quelle
1
niceund renice? Das ist schön! Ich habe mir die Handbuchseiten angesehen, aber ich glaube immer noch nicht, dass sie dabei helfen können, da Sie immer noch eine Prozess-ID festlegen müssen. Wenn Sie mir jedoch ein Beispiel geben könnten, das diese Pakete beinhaltet, um das Limit für alle laufenden Prozesse / zukünftigen Prozesse anzuwenden, wäre das fantastisch!
Giovanni Mounir
1

Da haben deine Tags centos , können Sie verwenden systemd.

Zum Beispiel, wenn Sie den Benutzer mit folgender ID einschränken möchten 1234:

sudo systemctl edit --force user-1234.slice

Dann tippe und speichere das:

[Slice] CPUQuota=10%

Wenn sich der Benutzer das nächste Mal anmeldet, wirkt sich dies aus.

Man Seiten: systemctl, systemd.slice, systemd.resource-control...

Stapel-Richtlinien-sind-Trolle
quelle
0

Wenn Sie die bereits gestarteten Prozesse einschränken möchten, müssen Sie dies nacheinander per PID tun. Sie können jedoch ein Batch-Skript verwenden, um dies wie das folgende zu tun:

#!/bin/bash
LIMIT_PIDS=$(pgrep tesseract)   # PIDs in queue replace tesseract with your name
echo $LIMIT_PIDS
for i in $LIMIT_PIDS
do
    cpulimit -p $i -l 10 -z &   # to 10 percent processes
done

In meinem Fall pypdfocrstartet das gierigtesseract .

Auch in einigen Fällen, in denen Ihre CPU ziemlich gut ist, können Sie einfach Folgendes verwenden renice:

watch -n5 'pidof tesseract | xargs -L1 sudo renice +19'
Eduard Florinescu
quelle