- Quel est le moyen le plus rapide de reprendre le contrôle d'un système Linux qui ne répond plus ou est extrêmement lent à cause d'un échange excessif?
Déjà répondu ci - dessus avec Alt-SysRq-F
- Existe-t-il un moyen efficace d'empêcher un tel échange de se produire en premier lieu, par exemple en limitant la quantité de mémoire qu'un processus est autorisé à essayer d'allouer?
Je réponds à cette 2ème partie. Oui, ulimit
fonctionne toujours assez bien pour limiter un seul processus. Vous pouvez:
- fixer une limite souple pour un processus dont vous savez qu'il sera probablement hors de contrôle
- fixer une limite stricte pour tous les processus si vous voulez une assurance supplémentaire
Aussi, comme brièvement mentionné:
Vous pouvez utiliser des groupes CG pour limiter l'utilisation des ressources et éviter de tels problèmes
En effet, les cgroups offrent un contrôle plus avancé, mais sont actuellement plus compliqués à configurer à mon avis.
Ulimit old school
Une fois éteint
Voici un exemple simple:
$ bash
$ ulimit -S -v $((1*2**20))
$ r2(){r2 $@$@;};r2 r2
bash: xmalloc: .././subst.c:3550: cannot allocate 134217729 bytes (946343936 bytes allocated)
Il:
- Définit une limite souple de 1 Go d'utilisation globale de la mémoire (ulimit suppose une limite en unité de Ko)
- Exécute un appel de fonction bash récursif qui mâchera de manière
r2(){ r2 $@$@;};r2 r2
exponentielle le CPU et la RAM en se doublant infiniment tout en demandant la mémoire de la pile.
Comme vous pouvez le voir, il s'est arrêté lors de la tentative de demande de plus de 1 Go.
Remarque, -v
fonctionne sur l'allocation de mémoire virtuelle (total, c'est-à-dire physique + échange).
Protection permanente
Pour limiter l'allocation de mémoire virtuelle, as
est l'équivalent de -v
for limits.conf
.
Je fais ce qui suit pour me protéger contre tout processus de mauvaise conduite:
- Définissez une limite d'espace d'adressage fixe pour tous les processus.
address space limit = <physical memory> - 256MB
.
- Par conséquent, aucun processus avec une utilisation gourmande de la mémoire ou une boucle active et une fuite de mémoire ne peut consommer TOUTE la mémoire physique.
- Une marge de 256 Mo est là pour un traitement essentiel avec ssh ou une console.
Bon mot:
$ 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"
Pour valider, cela se traduit par ce qui suit (par exemple sur un système de 16 Go):
$ cat /etc/security/limits.d/mem.conf
* hard as 16135196
$ ulimit -H -v
161351960
Remarques:
- Atténue uniquement contre un processus unique allant trop loin avec l'utilisation de la mémoire.
- N'empêchera pas une charge de travail multi-processus avec une forte pression mémoire provoquant un thrashing (cgroups est alors la réponse).
- N'utilisez pas d'
rss
option dans limits.conf. Il n'est pas respecté par les noyaux plus récents.
- C'est conservateur.
- En théorie, un processus peut demander de manière spéculative beaucoup de mémoire mais uniquement utiliser activement un sous-ensemble (plus petit ensemble de travail / utilisation de mémoire résidente).
- La limite stricte ci-dessus entraînera l'abandon de ces processus (même s'ils auraient sinon pu fonctionner correctement, étant donné que Linux permet de surcharger l'espace d'adressage de la mémoire virtuelle).
Nouveaux groupes CG
Offre plus de contrôle, mais actuellement plus complexe à utiliser:
- Améliore l'offre ulimit.
memory.max_usage_in_bytes
peut prendre en compte et limiter la mémoire physique séparément.
- Alors que
ulimit -m
et / ou rss
in limits.conf
étaient censés offrir des fonctionnalités similaires, mais cela ne fonctionne pas depuis le noyau Linux 2.4.30!
- Nécessité de permettre à certains indicateurs de CGroup du noyau dans bootloader:
cgroup_enable=memory swapaccount=1
.
- Cela ne s'est pas produit par défaut avec Ubuntu 16.04.
- Probablement en raison de certaines implications en termes de performances de frais généraux supplémentaires.
- Les éléments cgroup / systemd sont relativement nouveaux et changent un peu, donc le flux en amont implique que les fournisseurs de distribution Linux ne l'ont pas encore rendu facile à utiliser. Entre 14.04LTS et 16.04LTS, l'outillage de l'espace utilisateur pour utiliser les groupes de contrôle a changé.
cgm
semble maintenant être l'outil de l'espace utilisateur officiellement pris en charge.
- Les fichiers d'unité systemd ne semblent pas encore avoir de valeurs par défaut "fournisseur / distribution" pour prioriser des services importants comme ssh.
Par exemple, pour vérifier les paramètres actuels:
$ echo $(($(cat /sys/fs/cgroup/memory/memory.max_usage_in_bytes) / 2**20)) MB
11389 MB
$ cat /sys/fs/cgroup/memory/memory.stat
...
Par exemple pour limiter la mémoire d'un seul processus:
$ 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
Pour le voir en action mâcher de la RAM en tant que processus d'arrière-plan, puis se faire tuer:
$ 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'
Notez la croissance exponentielle (puissance de 2) des demandes de mémoire.
À l'avenir, espérons voir "distro / vendors" préconfigurer les priorités et les limites du groupe de contrôle (via les unités systemd) pour des choses importantes comme SSH et la pile graphique, de sorte qu'elles ne soient jamais affamées de mémoire.