- Jaki jest najszybszy sposób na odzyskanie kontroli nad systemem Linux, który przestał reagować lub był bardzo powolny z powodu nadmiernej wymiany?
Już odpowiedziałem powyżej za pomocą Alt-SysRq-F
- Czy istnieje skuteczny sposób, aby przede wszystkim zapobiec takiej zamianie, na przykład poprzez ograniczenie ilości pamięci, którą proces może przydzielić?
Odpowiadam na drugą część. Tak, ulimit
nadal działa wystarczająco dobrze, aby ograniczyć pojedynczy proces. Możesz:
- ustaw miękki limit dla procesu, o którym wiesz, że prawdopodobnie wymknie się spod kontroli
- ustaw sztywny limit dla wszystkich procesów, jeśli chcesz uzyskać dodatkowe ubezpieczenie
Ponadto, jak krótko wspomniano:
Możesz użyć CGroups, aby ograniczyć wykorzystanie zasobów i zapobiec takim problemom
Rzeczywiście, cgroups oferują bardziej zaawansowaną kontrolę, ale obecnie moim zdaniem są bardziej skomplikowane w konfiguracji.
Old school ulimit
Raz wolny
Oto prosty przykład:
$ bash
$ ulimit -S -v $((1*2**20))
$ r2(){r2 $@$@;};r2 r2
bash: xmalloc: .././subst.c:3550: cannot allocate 134217729 bytes (946343936 bytes allocated)
To:
- Ustawia miękki limit całkowitego wykorzystania pamięci 1 GB (ulimit zakłada limit w jednostkach kB)
- Uruchamia rekurencyjne wywołanie funkcji bash
r2(){ r2 $@$@;};r2 r2
, która wykładniczo przeżuwa procesor i pamięć RAM, nieskończenie podwajając się podczas żądania pamięci stosu.
Jak widać, został zatrzymany podczas próby żądania więcej niż 1 GB.
Uwaga, -v
działa na zasadzie alokacji pamięci wirtualnej (ogółem, tj. Fizyczna + zamiana).
Stała ochrona
Aby ograniczyć alokacji pamięci wirtualnej as
jest równoważny -v
dla limits.conf
.
Wykonuję następujące czynności, aby zabezpieczyć się przed jakimkolwiek niewłaściwym procesem:
- Ustaw sztywny limit przestrzeni adresowej dla wszystkich procesów.
address space limit = <physical memory> - 256MB
.
- Dlatego żaden pojedynczy proces z chciwym wykorzystaniem pamięci lub aktywną pętlą i przeciekiem pamięci nie może zająć CAŁEJ pamięci fizycznej.
- 256 MB miejsca jest potrzebne do niezbędnego przetwarzania za pomocą ssh lub konsoli.
Jedna wkładka:
$ 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"
Aby sprawdzić poprawność, wynik jest następujący (np. W systemie 16 GB):
$ cat /etc/security/limits.d/mem.conf
* hard as 16135196
$ ulimit -H -v
161351960
Uwagi:
- Łagodzi tylko jeden proces, który przesadza z wykorzystaniem pamięci.
- Nie zapobiegnie obciążeniu wieloprocesowemu przy dużej presji pamięci powodującej przeładowanie (wtedy cgroups jest odpowiedzią).
- Nie używaj
rss
opcji w limit.conf. Nie jest szanowany przez nowsze jądra.
- To jest konserwatywne.
- Teoretycznie proces może spekulacyjnie żądać dużej ilości pamięci, ale tylko aktywnie korzysta z podzbioru (mniejsze użycie zestawu roboczego / pamięci rezydentnej).
- Powyższy sztywny limit spowoduje przerwanie takich procesów (nawet jeśli mogłyby one działać poprawnie, ponieważ Linux pozwala na nadmierne wykorzystanie przestrzeni adresowej pamięci wirtualnej).
Nowsze grupy C
Oferuje większą kontrolę, ale obecnie jest bardziej skomplikowany w użyciu:
- Poprawiono ofertę ulimit.
memory.max_usage_in_bytes
może osobno rozliczać i ograniczać pamięć fizyczną.
- Natomiast
ulimit -m
i / lub rss
in limits.conf
miał oferować podobną funkcjonalność, ale to nie działa od jądra Linuksa 2.4.30!
- Potrzeba, aby umożliwić pewne flagi cgroup jądro bootloader:
cgroup_enable=memory swapaccount=1
.
- Nie zdarzyło się to domyślnie w Ubuntu 16.04.
- Prawdopodobnie z powodu pewnych skutków dodatkowych kosztów księgowych związanych z wydajnością.
- cgroup / systemd stuff jest stosunkowo nowy i zmienia się nieco, więc flux upstream sugeruje, że dostawcy dystrybucji Linuksa jeszcze nie ułatwili jego obsługi. Pomiędzy 14.04LTS a 16.04LTS zmieniło się oprzyrządowanie przestrzeni użytkownika do korzystania z cgroups.
cgm
teraz wydaje się być oficjalnie obsługiwanym narzędziem przestrzeni użytkownika.
- Wydaje się, że w plikach jednostek systemowych nie ma żadnych wstępnie zdefiniowanych wartości domyślnych „dostawca / dystrybucja”, aby nadać priorytet ważnym usługom, takim jak ssh.
Np. Aby sprawdzić bieżące ustawienia:
$ echo $(($(cat /sys/fs/cgroup/memory/memory.max_usage_in_bytes) / 2**20)) MB
11389 MB
$ cat /sys/fs/cgroup/memory/memory.stat
...
Np. Aby ograniczyć pamięć pojedynczego procesu:
$ 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
Aby zobaczyć, jak działa, przeżuwa pamięć RAM jako proces w tle, a następnie ginie:
$ 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'
Zwróć uwagę na wykładniczy (potęga 2) wzrost liczby żądań pamięci.
W przyszłości zobaczmy, jak „dystrybucja / dostawcy” wstępnie konfigurują priorytety i limity grupy (za pomocą jednostek systemowych) dla ważnych rzeczy, takich jak SSH i stos graficzny, tak aby nigdy nie brakowało im pamięci.