# Mälupiiride seadmine systemd ja cgroup'idega

> systemd MemoryMax PHP-FPM-ile: seadke mälupiir cgroup'iga, nagu php.net PHP2Shelli puhul soovitab, koos MemoryHigh, OOMPolicy ja kontrollkäskudega.

Allikas: https://phpsos.de/et/blog/speichergrenzen-systemd-cgroups/  
Seis: 25.10.2026  
Pakkuja: PHP SOS, PHP hädaabi ja serveri turvalisus. Kohene abi WhatsAppis: https://wa.me/491736494914?text=Tere%2C%20PHP%20SOS%2C%20vajame%20abi%20oma%20PHP-serveriga.%20Ettev%C3%B5te%3A%20%E2%80%A6%20Veebisait%3A%20%E2%80%A6

**Lühidalt:** PHP2Shelli üleminekumeetme `memory_limit=-1` jaoks vajab PHP-FPM PHP-st väljaspool asuvat mälupiiri. systemd all seate selle sättega `MemoryHigh=` pidurina ja `MemoryMax=` kõva ülempiirina FPM-teenuse täienduskaustas. `ulimit`, `LimitAS=` või `LimitDATA=` ei sobi selleks php.net'i järgi. Kontrollige lisaks `OOMPolicy=`, et üks töölisprotsess ei lõpetaks kogu teenust.

## Soovitus, mis esmalt hämmastab

php.net'i 21. oktoobril 2026 PHP2Shelli kohta avaldatud üleminekumeetmete hulgas on üks, mis pani paljud administraatorid imestama: `memory_limit=-1`, see tähendab mälupiiri puudumist PHP-s endas. Aastaid peeti vastupidist heaks tavaks.

Seos augu kirjeldusega on ilmne. CVE-2026-109618 puhul võib mälupuuduse olek PHP katkestada, kui päringuandmed on vaid osaliselt lähtestatud. Üleminekumeede nihutab mälupiiri PHP-st välja operatsioonisüsteemi. php.net seob selle otsesõnu kahe tingimusega: väärtus peab olema ülekirjutamise vastu lukustatud ja piir peab tulema konteineri või cgroup'i kaudu, mitte `RLIMIT_AS` või `RLIMIT_DATA` kaudu.

Kes rakendab ainult esimese poole, on saanud serveri ilma ühegi mälupiirita. See artikkel näitab teist poolt. Ka koos jääb meede üleminekuks: auk on parandatud alles versioonidega PHP 8.5.12, 8.4.27, 8.3.36, 8.2.35 või kinnitatud tagasiportimisega.

## cgroup'id kahes lauses

Control Groups, lühidalt cgroup'id, on Linuxi tuuma funktsioon, mis rühmitab protsesse ja piirab nende ressursse. systemd loob iga teenuse jaoks automaatselt oma cgroup'i ja kõik teenuse protsessid, FPM-teenuse puhul peaprotsess ja kõik töölised, kuuluvad sinna.

systemd mälusuvandid seavad cgroup v2 mälukontrolleri väärtusi. Kas teie süsteem kasutab cgroup v2, näitab lühike käsk:

```bash
# "cgroup2fs" tähendab: cgroup v2 on aktiivne
stat -fc %T /sys/fs/cgroup/
```

Levinumate distributsioonide praegused versioonid kasutavad cgroup v2 vaikimisi. Kui käsk näitab midagi muud, selgitage see enne ümberlülitust, sest systemd dokumentatsioon kirjeldab vanu v1-suvandeid aegunutena.

## systemd MemoryMax seadmine PHP-FPM-ile

Piir läheb täienduskausta, nn drop-in'i. Nii jääb paketi unit-fail muutmata ja uuendus teie sätet üle ei kirjuta. Teenuste nimed erinevad distributsiooniti; näide kasutab Debiani ja Ubuntut PHP 8.3-ga.

```ini
# Avab drop-in'i redaktori: sudo systemctl edit php8.3-fpm
# Tulemus: /etc/systemd/system/php8.3-fpm.service.d/override.conf
[Service]
MemoryAccounting=yes
MemoryHigh=1536M
MemoryMax=2G
MemorySwapMax=0
OOMPolicy=continue
```

Suvandite ülevaade systemd dokumentatsiooni järgi:

| Suvand | Mõju | Märkus PHP-FPM-i kohta |
|---|---|---|
| `MemoryHigh=` | piduripiir: protsesse pidurdatakse tugevalt, mälu võetakse tagasi | tegelik juhtsuurus, veidi `MemoryMax` all |
| `MemoryMax=` | absoluutne piir: kui seda ei suudeta hoida, aktiveerub teenuses OOM-killer | viimane kaitseliin |
| `MemorySwapMax=` | väljalaadimise piir | `0` takistab teenusel selle asemel swapi poole põigata |
| `OOMPolicy=` | käitumine pärast OOM-sündmust: `continue`, `stop` või `kill` | `continue` laseb ülejäänud töölistel edasi töötada |
| `LimitAS=`, `LimitDATA=` | rlimitid protsessi kohta | php.net'i järgi selle meetme jaoks sobimatud |

`OOMPolicy=` väärib erilist tähelepanu. Väärtuse `stop` või `kill` korral lõpetab systemd pärast OOM-sündmust kogu teenuse ja kõik selle FPM-teenuse veebisaidid kukuvad välja. Millist väärtust kasutatakse ilma oma määranguta, määrab süsteemi vaikesäte `DefaultOOMPolicy=`. Kontrollige kehtivat väärtust seetõttu, selle asemel et seda eeldada.

Seejärel taaskäivitage teenus ja lukustage poolis `memory_limit`:

```bash
sudo systemctl restart php8.3-fpm
systemctl show php8.3-fpm -p MemoryHigh -p MemoryMax -p MemorySwapMax -p OOMPolicy -p MemoryCurrent
```

```ini
; Pooli fail, nt /etc/php/8.3/fpm/pool.d/seite1.conf
php_admin_value[memory_limit] = -1
```

Kuidas lukustamine töötab, kirjeldab [php_admin_value: sätete kaitsmine ülekirjutamise eest](https://phpsos.de/et/blog/php-admin-value-sperren/).

## Õige väärtuse leidmine

Liiga napp piir tekitab katkestusi tavatöös, liiga helde ei kaitse peaaegu üldse. Lähtekoht on tegelik tarbimine.

1. Jälgige kõigi FPM-protsesside tegelikku mälutarvet mõne päeva jooksul, ka koormushetkedel.
2. Selgitage välja ühe töölise tüüpiline vajadus ja korrutage see teenuse kõigi poolide `pm.max_children` väärtustega.
3. Planeerige juurde peaprotsessi, OPcache'i ja tippude jaoks.
4. Seadke `MemoryHigh=` mõõdetud tipuväärtusest napilt kõrgemale, `MemoryMax=` veidi kaugemale selle kohale.
5. Kohandage väärtusi nädala pärast mõõtmiste ja OOM-sündmuste põhjal.

```bash
# Kõigi PHP-FPM-protsesside mälu MB-des (Resident Set Size)
ps -C php-fpm8.3 -o rss= | awk '{s+=$1} END {printf "%.0f MB\n", s/1024}'
# Kõigi cgroup'ide jooksev ülevaade mälu järgi sorteeritult
systemd-cgtop -m
```

`memory_limit` väärtuse märkige enne ümberlülitust üles. Pärast uuendust saate pöörduda tagasi PHP kindla piiri juurde; kuidas seda mõistlikult valida, on kirjas artiklis [memory_limit õige seadistamine](https://phpsos.de/et/blog/memory-limit-richtig-setzen/).

## Seire: millal piir rakendub

Mälupiir, mille rakendumist keegi ei märka, on vaikne veaallikas. Tuum loendab OOM-sündmusi cgroup'i kaupa ning systemd ja tuumaprotokoll märgivad need üles.

```bash
# Teenuse cgroup'i OOM-loendur (tee cgroup v2 korral)
cat /sys/fs/cgroup/system.slice/php8.3-fpm.service/memory.events
# OOM-killeri teated tuumaprotokollis
journalctl -k --since "-1 day" | grep -i "out of memory"
```

Kui loendur `oom_kill` kasvab, lõpetab tuum töölisi. See võib viidata liiga napile piirile, vigasele rakendusele või ebatavalistele päringutele. Praeguses olukorras tasub selliseid sündmusi samaaegsete pöördusprotokollidega võrrelda.

> **Oluline:**
> Mälupiir on üleminekumeede ega asenda PHP uuendust. Planeerige uuendus paralleelselt ja taaskäivitage seejärel kõik PHP protsessid. Kõik üleminekumeetmed ülevaatlikult on lehel [Kiirmeetmed, kui te ei saa veel paikama hakata](https://phpsos.de/et/php2shell/sofortmassnahmen-ohne-patch/).

Mis juhtub PHP sees mälupuuduse korral, selgitab [memory_limit ja Out-of-Memory](https://phpsos.de/et/php/out-of-memory/). Apache'i puhul mod_php-ga kehtib sama tehnika Apache'i teenuse kohta, ent PHP jagab piiri siis veebiserveri endaga.

## Kokkuvõte: ärge unustage teist poolt

`memory_limit=-1` on põhjendatav üleminekumeede ainult koos välise piiriga. systemd teeb selle piiri võimalikuks mõne reaga: `MemoryHigh` pidurina, `MemoryMax` kõva ülempiirina, `MemorySwapMax` swapi poole põikamise vastu ja teadlikult valitud `OOMPolicy`. Mõõtke enne, jälgige pärast ja pidage meeles, et ühe teenuse kõik poolid jagavad piiri.

Peamine aga: planeerige meetme lõpp. Pärast uuendust parandatud PHP versioonile pöörduge tagasi kindla `memory_limit` juurde. cgroup'i piiri võite säilitada täiendava kaitsena väljaulatuvate protsesside vastu.

## Kuidas PHP SOS konkreetselt aitab?

- **Mõõta:** kaardistame teie PHP teenuste mälutarbe ja tuletame sellest sobivad piirid.
- **Rakendada:** seame drop-in'id sätetega `MemoryHigh`, `MemoryMax` ja sobiva `OOMPolicy`, lukustame poolis `memory_limit` ja taaskäivitame teenused kontrollitult.
- **Jälgida:** põimime OOM-sündmused seiresse ja kohandame väärtusi.
- **Viia paigani:** [PHP paigateenuse](https://phpsos.de/et/leistungen/php-patch-service/) kaudu paigaldame uuenduse ja võtame üleminekuväärtused seejärel korrapäraselt tagasi.


## Korduma kippuvad küsimused

**Miks peab memory_limit olema -1? Kas see pole ohtlik?**  
Üksi oleks. php.net soovitab memory_limit=-1 üleminekumeetmena otsesõnu koos mälupiiriga konteineri või cgroup'i kaudu. Piiramine liigub niimoodi PHP-st välja operatsioonisüsteemi. Ilma selle välise piirita ei tohiks väärtust seada.

**Kas saan selle asemel kasutada ulimit'i või LimitAS=?**  
Ei. php.net soovitab RLIMIT_AS-i ja RLIMIT_DATA-t otsesõnu mitte kasutada ning just neid piire seavad ulimit -v, LimitAS= ja LimitDATA=. systemd dokumentatsioon juhib lisaks tähelepanu, et LimitAS= piirab aadressiruumi, mitte mälukasutust.

**Mis juhtub, kui PHP-FPM piirini jõuab?**  
MemoryHigh puhul pidurdab tuum protsesse ja võtab mälu tagasi. MemoryMax puhul aktiveerub teenuse sees OOM-killer ja lõpetab ühe protsessi, enamasti suure töölise. Kas kogu teenus pärast seda peatub, reguleerib OOMPolicy=.

**Kas piir kehtib iga pooli kohta eraldi?**  
Ei. Ühe FPM-teenuse kõik poolid jagavad ühte cgroup'i ja seega ühist piiri. Veebisaitide kaupa eraldi piirid vajavad eraldi FPM-teenuseid või konteinereid.

**Kuidas seada piir Dockeris või Kubernetes'es?**  
Konteineri mälupiirangu kaudu, näiteks valikuga --memory käsus docker run või resources.limits.memory Kubernetes'es. Mõlemad kasutavad samuti cgroup'e. Põhimõte jääb samaks: piir väljaspool PHP-d, memory_limit PHP-s lukustatud.

## Allikad

- [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: turvateated](https://www.php.net/)
- [PHP käsiraamat: memory_limit](https://www.php.net/manual/en/ini.core.php)
