- Qual è il modo più rapido per riprendere il controllo di un sistema Linux diventato non reattivo o estremamente lento a causa dell'eccessivo scambio?
Ho già risposto sopra con Alt-SysRq-F
- Esiste un modo efficace per impedire che tale scambio avvenga in primo luogo, ad esempio limitando la quantità di memoria che un processo può tentare di allocare?
Sto rispondendo a questa seconda parte. Sì, ulimit
funziona ancora abbastanza bene per limitare un singolo processo. Puoi:
- impostare un limite leggero per un processo che probabilmente andrà fuori controllo
- impostare un limite rigido per tutti i processi se si desidera un'assicurazione aggiuntiva
Inoltre, come brevemente menzionato:
È possibile utilizzare CGroup per limitare l'utilizzo delle risorse e prevenire tali problemi
In effetti, i cgroups offrono un controllo più avanzato, ma attualmente sono più complicati da configurare secondo me.
Ulimit vecchia scuola
Una volta fuori
Ecco un semplice esempio:
$ bash
$ ulimit -S -v $((1*2**20))
$ r2(){r2 $@$@;};r2 r2
bash: xmalloc: .././subst.c:3550: cannot allocate 134217729 bytes (946343936 bytes allocated)
It:
- Imposta un limite soft per l'utilizzo della memoria complessiva da 1 GB (ulimit assume il limite in unità kB)
- Esegue una chiamata di funzione bash ricorsiva
r2(){ r2 $@$@;};r2 r2
che mastica esponenzialmente CPU e RAM raddoppiando infinitamente se stessa mentre richiede la memoria dello stack.
Come puoi vedere, si è arrestato quando si è cercato di richiedere più di 1 GB.
Nota, -v
opera sull'allocazione di memoria virtuale (totale, cioè fisica + swap).
Protezione permanente
Per limitare l'allocazione di memoria virtuale, as
è l'equivalente di -v
per limits.conf
.
Faccio quanto segue per proteggermi da ogni singolo processo di comportamento scorretto:
- Impostare un limite di spazio per l'indirizzo fisso per tutti i processi.
address space limit = <physical memory> - 256MB
.
- Pertanto, nessun singolo processo con avido utilizzo della memoria o un loop attivo e una perdita di memoria può consumare TUTTA la memoria fisica.
- Un headroom di 256 MB è lì per l'elaborazione essenziale con ssh o una console.
Una fodera:
$ sudo bash -c "echo -e \"*\thard\tas\t$(($(grep -E 'MemTotal' /proc/meminfo | grep -oP '(?<=\s)\d+(?=\skB$)') - 256*2**10))\" > /etc/security/limits.d/mem.conf"
Per convalidare, ciò si traduce in quanto segue (ad es. Su un sistema da 16 GB):
$ cat /etc/security/limits.d/mem.conf
* hard as 16135196
$ ulimit -H -v
161351960
Appunti:
- Riduce solo un singolo processo che va in mare con l'uso della memoria.
- Non impedirà un carico di lavoro multi-processo con una forte pressione della memoria che causa il thrashing (cgroups è quindi la risposta).
- Non utilizzare l'
rss
opzione in limits.conf. Non è rispettato dai kernel più recenti.
- È conservatore.
- In teoria, un processo può richiedere speculativamente molta memoria ma utilizzare attivamente solo un sottoinsieme (set di lavoro più piccolo / uso della memoria residente).
- Il suddetto limite rigido causerà l'interruzione di tali processi (anche se potrebbero altrimenti funzionare correttamente dato che Linux consente lo spazio di indirizzi della memoria virtuale per essere sovraccaricato).
CGgr più recenti
Offre un maggiore controllo, ma attualmente più complesso da usare:
- Migliora l'offerta ulimit.
memory.max_usage_in_bytes
può rendere conto e limitare la memoria fisica separatamente.
- Considerando che
ulimit -m
e / o rss
in limits.conf
doveva offrire funzionalità simili, ma non funziona dal kernel Linux 2.4.30!
- Devi abilitare alcune bandiere kernel cgroup in bootloader:
cgroup_enable=memory swapaccount=1
.
- Questo non è accaduto di default con Ubuntu 16.04.
- Probabilmente a causa di alcune implicazioni prestazionali di spese generali di contabilità aggiuntive.
- roba cgroup / systemd è relativamente nuova e sta cambiando un po ', quindi il flusso a monte implica che i fornitori di distribuzione Linux non hanno ancora reso facile da usare. Tra 14.04LTS e 16.04LTS, gli strumenti dello spazio utente per utilizzare i cgroup sono cambiati.
cgm
ora sembra essere lo strumento userspace ufficialmente supportato.
- i file di unità di sistema non sembrano ancora avere impostazioni predefinite "vendor / distro" per dare priorità a servizi importanti come ssh.
Ad esempio per verificare le impostazioni correnti:
$ echo $(($(cat /sys/fs/cgroup/memory/memory.max_usage_in_bytes) / 2**20)) MB
11389 MB
$ cat /sys/fs/cgroup/memory/memory.stat
...
Ad esempio per limitare la memoria di un singolo processo:
$ cgm create memory mem_1G
$ cgm setvalue memory mem_1G memory.limit_in_bytes $((1*2**30))
$ cgm setvalue memory mem_1G memory.memsw.limit_in_bytes $((1*2**30))
$ bash
$ cgm movepid memory mem_1G $$
$ r2(){ r2 $@$@;};r2 r2
Killed
Per vederlo in azione masticare la RAM come processo in background e poi essere ucciso:
$ bash -c 'cgm movepid memory mem_1G $$; r2(){ r2 $@$@;};r2 r2' & while [ -e /proc/$! ]; do ps -p $! -o pcpu,pmem,rss h; sleep 1; done
[1] 3201
0.0 0.0 2876
102 0.2 44056
103 0.5 85024
103 1.0 166944
...
98.9 5.6 920552
99.1 4.3 718196
[1]+ Killed bash -c 'cgm movepid memory mem_1G $$; r2(){ r2 $@$@;};r2 r2'
Nota la crescita esponenziale (potenza di 2) nelle richieste di memoria.
In futuro, speriamo di vedere "distro / vendor" preconfigurare priorità e limiti del cgroup (tramite unità systemd) per cose importanti come SSH e lo stack grafico, in modo tale da non perdere la memoria.