# Memóriahatárok beállítása systemd-vel és cgroupokkal

> systemd MemoryMax a PHP-FPM-hez: memóriahatár cgroupon át, ahogyan a php.net a PHP2Shellhez javasolja, MemoryHigh-jal, OOMPolicy-val és parancsokkal.

Forrás: https://phpsos.de/hu/blog/speichergrenzen-systemd-cgroups/  
Állapot: 2026. 10. 25.  
Szolgáltató: PHP SOS, PHP-vészhelyzeti segítség és szerverbiztonság. Azonnali segítség WhatsAppon: https://wa.me/491736494914?text=%C3%9Cdv%C3%B6zl%C3%B6m%2C%20PHP%20SOS%21%20Seg%C3%ADts%C3%A9gre%20van%20sz%C3%BCks%C3%A9g%C3%BCnk%20a%20PHP-szerver%C3%BCnkkel.%20C%C3%A9g%3A%20%E2%80%A6%20Weboldal%3A%20%E2%80%A6

**Röviden:** A `memory_limit=-1` PHP2Shell-átmeneti intézkedéshez a PHP-FPM-nek a PHP-n kívüli memóriahatárra van szüksége. A systemd alatt ezt a `MemoryHigh=` féktényezővel és a `MemoryMax=` kemény felső határral állítsa be az FPM-szolgáltatás kiegészítő fájljában. Az `ulimit`, a `LimitAS=` vagy a `LimitDATA=` a php.net szerint erre alkalmatlan. Ellenőrizze emellett az `OOMPolicy=` értékét, hogy egyetlen worker ne állítsa le az egész szolgáltatást.

## Egy ajánlás, amely elsőre meglepő

A php.net által 2026. október 21-én a PHP2Shellről közzétett átmeneti intézkedések között van egy, amely sok adminisztrátort megállított: `memory_limit=-1`, vagyis nincs memóriahatár magában a PHP-ban. Éveken át az ellenkezője számított jó gyakorlatnak.

A rés leírásával való összefüggés kézenfekvő. A CVE-2026-109618 esetében egy Out-of-Memory állapot megszakíthatja a PHP-t, miközben a kérésadatok csak részben vannak inicializálva. Az átmeneti intézkedés a memóriahatárt kihelyezi a PHP-ból az operációs rendszerbe. A php.net kifejezetten két feltételhez köti: az értéknek zároltnak kell lennie a felülírás ellen, és a határnak konténeren vagy cgroupon keresztül kell érkeznie, nem az `RLIMIT_AS` vagy `RLIMIT_DATA` útján.

Aki csak az első felét valósítja meg, annak olyan szervere lesz, amelyen semmilyen memóriahatár nincs. Ez a cikk a második felet mutatja. Együtt is átmenet marad az intézkedés: a rés csak a PHP 8.5.12, 8.4.27, 8.3.36, 8.2.35 vagy egy megerősített backport révén szűnik meg.

## A cgroupok két mondatban

A Control Groups, röviden cgroupok, a Linux-kernel egy funkciója, amely csoportosítja a folyamatokat, és korlátozza az erőforrásaikat. A systemd minden szolgáltatáshoz automatikusan saját cgroupot hoz létre, és a szolgáltatás összes folyamata, az FPM-szolgáltatásnál tehát a master és az összes worker, ahhoz tartozik.

A systemd memóriaopciói a cgroup v2 memóriavezérlőjének értékeit állítják be. Hogy a rendszere használ-e cgroup v2-t, azt egy rövid parancs mutatja:

```bash
# A „cgroup2fs” azt jelenti: a cgroup v2 aktív
stat -fc %T /sys/fs/cgroup/
```

A gyakori disztribúciók aktuális verziói alapértelmezetten cgroup v2-t használnak. Ha a parancs mást mutat, az átállás előtt tisztázza ezt, mert a systemd dokumentációja a régi v1-opciókat elavultként írja le.

## A systemd MemoryMax beállítása a PHP-FPM-hez

A határ egy kiegészítő fájlba, úgynevezett drop-inbe kerül. Így a csomag unit-fájlja változatlan marad, és egy frissítés nem írja felül az Ön beállítását. A szolgáltatásnevek disztribúciónként eltérnek; a példa Debiant és Ubuntut használ PHP 8.3-mal.

```ini
# Megnyit egy szerkesztőt a drop-inhez: sudo systemctl edit php8.3-fpm
# Eredmény: /etc/systemd/system/php8.3-fpm.service.d/override.conf
[Service]
MemoryAccounting=yes
MemoryHigh=1536M
MemoryMax=2G
MemorySwapMax=0
OOMPolicy=continue
```

Az opciók áttekintése a systemd dokumentációja szerint:

| Opció | Hatás | Megjegyzés a PHP-FPM-hez |
|---|---|---|
| `MemoryHigh=` | fojtási határ: a folyamatokat erősen lassítják, memóriát szereznek vissza | a tényleges szabályozó érték, valamivel a `MemoryMax` alatt |
| `MemoryMax=` | abszolút határ: ha nem tartható, aktívvá válik a szolgáltatáson belüli OOM-killer | utolsó védelmi vonal |
| `MemorySwapMax=` | a kiszervezés határa | a `0` megakadályozza, hogy a szolgáltatás helyette a swapbe térjen ki |
| `OOMPolicy=` | viselkedés egy OOM-esemény után: `continue`, `stop` vagy `kill` | a `continue` hagyja tovább futni a többi workert |
| `LimitAS=`, `LimitDATA=` | rlimitek folyamatonként | a php.net szerint erre az intézkedésre alkalmatlan |

Az `OOMPolicy=` különös figyelmet érdemel. `stop` vagy `kill` esetén a systemd egy OOM-esemény után leállítja az egész szolgáltatást, és az FPM-szolgáltatás összes weboldala kiesik. Hogy saját megadás nélkül melyik érték érvényes, azt a `DefaultOOMPolicy=` rendszeralapérték rögzíti. Ezért ellenőrizze a hatályos értéket, ahelyett hogy feltételezné.

Ezután indítsa újra a szolgáltatást, és zárolja a `memory_limit` értékét a poolban:

```bash
sudo systemctl restart php8.3-fpm
systemctl show php8.3-fpm -p MemoryHigh -p MemoryMax -p MemorySwapMax -p OOMPolicy -p MemoryCurrent
```

```ini
; Pool-fájl, pl. /etc/php/8.3/fpm/pool.d/seite1.conf
php_admin_value[memory_limit] = -1
```

Hogyan működik a zárolás, azt a [php_admin_value: beállítások zárolása a felülírás ellen](https://phpsos.de/hu/blog/php-admin-value-sperren/) írja le.

## A helyes érték megtalálása

Egy túl szűk határ megszakításokat okoz a normál üzemben, egy túl nagyvonalú alig véd. A kiindulópont a tényleges fogyasztás.

1. Figyelje néhány napon át az összes FPM-folyamat tényleges memóriaigényét, a terhelési csúcsok idején is.
2. Állapítsa meg egy worker tipikus igényét, és szorozza meg a szolgáltatás összes poolja `pm.max_children` értékével.
3. Tervezzen felárat a master folyamatra, az OPcache-re és a csúcsokra.
4. A `MemoryHigh=` értéket a mért csúcsérték fölé, kissé szorosan állítsa be, a `MemoryMax=` értéket némi távolsággal fölé.
5. Egy hét után igazítsa az értékeket a mérések és az OOM-események alapján.

```bash
# Az összes PHP-FPM-folyamat memóriája MB-ban (Resident Set Size)
ps -C php-fpm8.3 -o rss= | awk '{s+=$1} END {printf "%.0f MB\n", s/1024}'
# Az összes cgroup folyamatos áttekintése memória szerint rendezve
systemd-cgtop -m
```

A `memory_limit` értékét az átállás előtt jegyezze fel. A frissítés után visszatérhet a PHP-ban egy rögzített határhoz; hogyan válassza meg ezt értelmesen, azt a [memory_limit helyes beállítása](https://phpsos.de/hu/blog/memory-limit-richtig-setzen/) cikk írja le.

## Felügyelet: mikor lép működésbe a határ

Egy olyan memóriahatár, amelynek kiváltódását senki sem veszi észre, csendes hibaforrás. A kernel cgroupokként számolja az OOM-eseményeket, és a systemd valamint a kernelnapló feljegyzi őket.

```bash
# A szolgáltatás cgroupjának OOM-számlálója (útvonal cgroup v2 esetén)
cat /sys/fs/cgroup/system.slice/php8.3-fpm.service/memory.events
# Az OOM-killer üzenetei a kernelnaplóban
journalctl -k --since "-1 day" | grep -i "out of memory"
```

Ha az `oom_kill` számláló emelkedik, a kernel workereket állít le. Ez utalhat túl szűk határra, hibás alkalmazásra vagy szokatlan kérésekre. A jelenlegi helyzetben megéri az ilyen eseményeket egybevetni az ugyanezen időpontbeli hozzáférési naplókkal.

> **Fontos:**
> A memóriahatár átmeneti intézkedés, és nem pótolja a PHP-frissítést. Tervezze párhuzamosan a frissítést, és utána indítsa újra az összes PHP-folyamatot. Az összes átmeneti intézkedés áttekintése az [Azonnali intézkedések, ha még nem tud javítani](https://phpsos.de/hu/php2shell/sofortmassnahmen-ohne-patch/) oldalon található.

Hogy mi történik a PHP belsejében memóriahiány esetén, azt a [memory_limit és Out-of-Memory](https://phpsos.de/hu/php/out-of-memory/) magyarázza. Az Apache-nál mod_php esetén ugyanez a technika érvényes az Apache-szolgáltatásra, a PHP azonban ekkor magával a webszerverrel osztozik a határon.

## Összegzés: ne feledkezzen meg a második feléről

A `memory_limit=-1` csak külső határral együtt vállalható átmeneti intézkedés. A systemd néhány sorral lehetővé teszi ezt a határt: a `MemoryHigh` fékként, a `MemoryMax` kemény felső határként, a `MemorySwapMax` a swapbe való kitérés ellen, és egy tudatosan választott `OOMPolicy`. Előtte mérjen, utána figyeljen, és tartsa szem előtt, hogy egy szolgáltatás összes poolja osztozik a határon.

De mindenekelőtt: tervezze meg az intézkedés végét. A javított PHP-verzióra való frissítés után térjen vissza egy rögzített `memory_limit` értékhez. A cgroup-határt kiegészítő védelemként megtarthatja az elszabaduló folyamatok ellen.

## Hogyan segít konkrétan a PHP SOS?

- **Mérés:** Felmérjük a PHP-szolgáltatásai memóriaigényét, és ebből levezetjük a megfelelő határokat.
- **Megvalósítás:** `MemoryHigh`, `MemoryMax` és megfelelő `OOMPolicy` értékkel drop-ineket állítunk be, zároljuk a `memory_limit` értékét a poolban, és a szolgáltatásokat ellenőrzötten újraindítjuk.
- **Megfigyelés:** Az OOM-eseményeket bevonjuk a felügyeletbe, és utánigazítjuk az értékeket.
- **Eljuttatás a javításig:** A [PHP-javítási szolgáltatáson](https://phpsos.de/hu/leistungen/php-patch-service/) keresztül telepítjük a frissítést, majd rendezetten visszavonjuk az átmeneti értékeket.


## Gyakori kérdések

**Miért kell a memory_limit értékének -1-nek lennie? Nem veszélyes ez?**  
Önmagában az lenne. A php.net a memory_limit=-1 értéket átmeneti intézkedésként kifejezetten konténeren vagy cgroupon keresztüli memóriahatárral együtt javasolja. A korlátozás így kikerül a PHP-ból az operációs rendszerbe. Ezen külső határ nélkül ne állítsa be az értéket.

**Használhatom helyette az ulimit-et vagy a LimitAS=-t?**  
Nem. A php.net kifejezetten óv az RLIMIT_AS és RLIMIT_DATA használatától, és éppen ezeket a határokat állítja be az ulimit -v, a LimitAS= és a LimitDATA=. A systemd dokumentációja ezenkívül rámutat, hogy a LimitAS= a címteret korlátozza, nem a memóriahasználatot.

**Mi történik, ha a PHP-FPM eléri a határt?**  
A MemoryHigh esetén a kernel lassítja a folyamatokat, és memóriát szerez vissza. A MemoryMax esetén a szolgáltatáson belül aktívvá válik az OOM-killer, és leállít egy folyamatot, többnyire egy nagy workert. Hogy utána az egész szolgáltatás leáll-e, azt az OOMPolicy= szabályozza.

**Minden poolra külön érvényes a határ?**  
Nem. Egy FPM-szolgáltatás összes poolja egy cgroupon osztozik, és így egy közös határon. A weboldalanként külön határokhoz külön FPM-szolgáltatások vagy konténerek kellenek.

**Hogyan állítom be a határt Dockerben vagy Kubernetesben?**  
A konténer memóriakorlátozásán keresztül, például a docker run --memory opciójával vagy a Kubernetesben a resources.limits.memory-val. Mindkettő szintén cgroupokat használ. Az alapelv ugyanaz marad: határ a PHP-n kívül, a memory_limit zárolva a PHP-ban.

## Források

- [systemd.resource-control (MemoryMax, MemoryHigh)](https://www.freedesktop.org/software/systemd/man/latest/systemd.resource-control.html)
- [systemd.service (OOMPolicy)](https://www.freedesktop.org/software/systemd/man/latest/systemd.service.html)
- [php.net: biztonsági közlemények](https://www.php.net/)
- [PHP kézikönyv: memory_limit](https://www.php.net/manual/en/ini.core.php)
