Limitare i processi a non superare più del 10% dell'utilizzo della CPU


32

Gestisco un sistema Linux che ha molti utenti ma a volte si verifica un abuso; dove un utente potrebbe eseguire un singolo processo che utilizza oltre l'80% della CPU / memoria.

Quindi c'è un modo per evitare che ciò accada limitando la quantità di utilizzo della CPU che un processo può usare (al 10% per esempio)? Sono a conoscenza cpulimit, ma sfortunatamente applica il limite ai processi che incarico di limitare (ad es. Singoli processi). Quindi la mia domanda è: come posso applicare il limite a tutti i processi in esecuzione e i processi che verranno eseguiti in futuro senza la necessità di fornire il loro ID / percorso, ad esempio?


Stai riscontrando problemi di prestazioni? o sono solo i numeri che ti danno fastidio?
ctrl-alt-delor

@richard Problemi di prestazioni, quindi è per questo che stavo cercando di eliminare / limitare / mettere fine ai processi che sembrano usare molta CPU, ma l'ho già fatto scrivendo uno script bash. Questa è anche una macchina virtuale se questo aiuta
Giovanni Mounir,

2
Fai attenzione ai processi di uccisione che possono essere al 100% per un tempo molto breve, anche ai processi di sistema. Considera cpulimitinsieme al tuo script di ricerca. Avere una politica e raccomandare l'uso di cpulimit, quindi cercare oltre il 10% e quindi limitare al 5% (quindi gli utenti sono incoraggiati a utilizzare cpulimit). Assicurati inoltre di poter rilevare più processi aggiungendo fino a oltre il 10% per un singolo utente.
ctrl-alt-delor

@richard Grazie Richard per tutti questi commenti piuttosto utili! Mi hanno aiutato moltissimo! Il tuo suggerimento di utilizzare cpulimitè molto meglio che semplicemente uccidere il processo poiché può essere riavviato dall'utente in seguito (come indicato in uno dei tuoi commenti). Grazie!
Giovanni Mounir,

Risposte:


20

Sebbene possa essere un abuso della memoria, non lo è per la CPU: quando una CPU è inattiva, un processo in esecuzione ("in esecuzione", intendo che il processo non è in attesa di I / O o qualcos'altro) richiederà Tempo di CPU 100% per impostazione predefinita. E non c'è motivo di imporre un limite.

Ora puoi impostare le priorità grazie a nice. Se vuoi che si applichino a tutti i processi per un determinato utente, devi solo assicurarti che la sua shell di accesso venga eseguita nice: i processi figlio erediteranno il nicevalore. Questo dipende dal modo in cui gli utenti effettuano l'accesso. Per esempio, vedi Priorità agli accessi ssh (bello) .

In alternativa, è possibile configurare macchine virtuali. In effetti, impostare un limite per processo non ha molto senso poiché l'utente può avviare molti processi, abusando del sistema. Con una macchina virtuale, tutti i limiti saranno globali per la macchina virtuale.

Un'altra soluzione è fissare /etc/security/limits.conflimiti; vedere la pagina man limits.conf (5). Ad esempio, è possibile impostare il tempo massimo della CPU per accesso e / o il numero massimo di processi per accesso. Puoi anche impostare maxlogins1 per ogni utente.


1
@GiovanniMounir Intendevo: una macchina virtuale per utente.
vinc17,

1
Vedo, ma sfortunatamente questo richiederà un dispendio di risorse e non sarà davvero utile per il mio scopo, poiché gli utenti potrebbero richiedere l'uso di alcuni pacchetti di sviluppo comuni e non lo installerò su ogni singola nuova macchina; Penso che sia meglio lasciarlo così e fare automaticamente il monitoraggio con uno script bash.
Giovanni Mounir,

1
@GiovanniMounir È possibile condividere una partizione tra più macchine virtuali.
vinc17,

@GiovanniMounir È possibile utilizzare LXC o Docker per ridurre l'overhead della virtualizzazione a quasi zero. Anche il "gradimento" non è un motivo forte. Ad esempio, andrei con la tua soluzione se gestisci un host PHP condiviso perché fare LXC o macchine virtuali richiederà la riscrittura di un software con licenza $ 15 / $ 5 che è eccessivo.
Pooyan Khosravi,

la mia comprensione è che Nice imposta solo la CPU relativa rispetto ad altri processi. Se nessun altro processo utilizza la CPU, il processo utilizzerà la CPU al 100%, non limitata al 10%.
johny perché il

25

bello / renice

nice è un ottimo strumento per apportare modifiche "uniche" a un sistema.

 nice COMMAND

cpulimit

cpulimit se è necessario eseguire un lavoro intensivo della CPU e disporre di tempo libero della CPU è essenziale per la reattività di un sistema.

cpulimit -l 50 COMMAND

cgroups

cgroups applicare limiti a una serie di processi, piuttosto che a uno solo

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

risorse

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


5
Per coloro che cercano di impostare un limite rigido per l'utilizzo della CPU, anche quando nessun altro processo è in esecuzione, consultare il cpu.cfs_quota_usparametro (consultare il manuale )
Diego

i cgroup sono più facili da usare grazie alle direttive systemd ... creare un'unità che sia il sistema o l'utente a tale scopo è l'opzione migliore
Yves Martin

per un processo in corso es .:sudo cgclassify -g cpu:cpulimited 2315444
Aquarius Power il

1
la mia comprensione è che Nice imposta solo la CPU relativa rispetto ad altri processi. Se nessun altro processo utilizza la CPU, il processo utilizzerà la CPU al 100%, non limitata al 10%.
johny perché il

10

Hai guardato i cgroups? Ci sono alcune informazioni su Arch Wiki al riguardo. Leggi la sezione su cpu.shares, sembra che stia facendo ciò di cui hai bisogno e che possono operare a livello di utente, quindi puoi limitare tutti i processi utente contemporaneamente.


CGroups è la strada da percorrere, però. Gestisco anche (molti) server di computer condivisi e utilizziamo i cgroup per limitare il numero massimo di core che può utilizzare un'intera sessione di accesso . In questo modo, se la persona continua ad avviare nuovi processi, ognuno ottiene una porzione più piccola. Lo stesso per l'uso della memoria. Puoi fare in modo che gli utenti inseriscano automaticamente in un cgroup con pam_cgroups e il servizio cgrulesengd. È possibile utilizzare un "modello" nel file cgconfig per inserire ciascun utente nel proprio cgroup. cgrulesengd si comporta come il tuo script, tranne che invece di uccidere i processi, si assicura solo che ogni processo sia nel giusto cgroup.
jsbillings,

Anche se non usi cgroups per limitare l'uso delle risorse, puoi usarlo per valutare quante risorse sta usando un individuo, guardando il file 'stat' per ogni risorsa, quindi usa quelle informazioni per il tuo script di 5 minuti.
jsbillings,

3

Per la memoria, quello che stai cercando è ulimit -v. Si noti che ulimitè ereditato da processi figlio, quindi se lo si applica alla shell di accesso dell'utente al momento dell'accesso, si applica a tutti i suoi processi.

Se tutti gli utenti utilizzano bashcome shell di accesso, l'inserimento della seguente riga /etc/profiledovrebbe comportare che tutti i processi utente abbiano un limite rigido di 1 gigabyte (più precisamente, un milione di kilobyte):

ulimit -vH 1000000

L'opzione Hassicura che sia un limite rigido, ovvero l'utente non può ripristinarlo in seguito. Naturalmente l'utente può ancora riempire la memoria avviando abbastanza processi contemporaneamente.

Per altre shell, dovrai scoprire quali file di inizializzazione leggono invece (e quali altri comandi invece di ulimitusare).

Per la CPU, ciò che desideri non sembra avere senso per me. A cosa servirebbe lasciare inutilizzato il 90% della CPU quando è in esecuzione un solo processo? Penso che ciò che vuoi davvero sia nice(e possibilmente ionice). Si noti che, come ulimit, i nicevalori sono ereditati dai processi figlio, quindi è sufficiente applicarlo alla shell di accesso al momento dell'accesso. Immagino che valga anche per ionicema non ne sono sicuro.


Grazie per il suggerimento sulla memoria! C'è qualche possibilità che tu possa mostrarmi un esempio per applicarlo alla shell di accesso dell'utente al momento dell'accesso? Non sono davvero sicuro di come farlo. Mi dispiace anche per non essere abbastanza chiaro; quello che sto cercando di fare è non consentire ad alcun processo di utilizzare più del 10% della CPU. Quindi pensi che nicesarà abbastanza carino per farlo? Se è così, pensi di potermi mostrare un esempio per raggiungere questo obiettivo?
Giovanni Mounir,

Non riesco ancora a mantenere la CPU inattiva al 90% quando è in esecuzione un solo processo.
celtschk,

1
Se al momento ci sono meno di 10 processi in esecuzione contemporaneamente (e per esecuzione intendo davvero in esecuzione, non solo in attesa dell'input dell'utente o dell'I / O del disco), allora è praticamente garantito che uno di essi avrà più del 10% di CPU. Altrimenti la CPU sarebbe praticamente inattiva. E se uccidi qualsiasi processo che supera il 10%, sono sicuro che avrai molti utenti che vorranno ucciderti . O almeno, cercherà di farti sostituire da qualcuno che ha la minima idea di cosa significhino quei numeri, perché non sembri.
Celtschk,

Contrariamente al commento di @celtschk, se ci sono 11 o più processi in esecuzione (cpu associato), saranno inferiori al 9,09%. Quindi, se sono un utente di un sistema che vieta un utilizzo della CPU superiore al 10%, posso eseguire 11 o più processi e nascondermi sotto il radar.
ctrl-alt-delor

@richard Hai ragione, forse sarebbe meglio se lo script riassumesse la quantità totale di memoria / CPU utilizzata da un utente, e quindi terminasse tutti i processi di questo utente quando la percentuale raggiunge una quantità specifica (quindi lo registrerebbe anche fuori)
Giovanni Mounir,

3

Dal momento che stai affermando che cpulimit non sarebbe pratico nel tuo caso, allora ti suggerisco di guardare nice , renice e tasket , che potrebbero avvicinarsi a ciò che vuoi ottenere, anche se tasket consente di impostare l'affinità della CPU di un processo, quindi potrebbe non essere immediatamente utile nel tuo caso.


1
nicee renice? Bello! Ho guardato le loro pagine di manuale, ma non credo ancora che possano esserti di aiuto in quanto devi comunque impostare un ID processo. Se potessi comunque darmi un esempio che coinvolge questi pacchetti per applicare il limite a tutti i processi in esecuzione / processi futuri sarebbe fantastico!
Giovanni Mounir,

1

Dal momento che i tag hanno centos, è possibile utilizzare systemd.

Ad esempio, se si desidera limitare l'utente con ID di 1234:

sudo systemctl edit --force user-1234.slice

Quindi digitare e salvare questo:

[Slice] CPUQuota=10%

La prossima volta che l'utente accede, avrà effetto.

Le pagine man: systemctl, systemd.slice, systemd.resource-control...


0

Se vuoi limitare i processi che sono già stati avviati, dovrai farlo uno per uno tramite PID, ma puoi avere uno script batch per farlo come quello qui sotto:

#!/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

Nel mio caso pypdfocrlancia l'avido tesseract.

Anche in alcuni casi dove la tua CPU è abbastanza buona puoi semplicemente usare una renicecome questa:

watch -n5 'pidof tesseract | xargs -L1 sudo renice +19'
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.