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:
# 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.
# 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:
sudo systemctl restart php8.3-fpm
systemctl show php8.3-fpm -p MemoryHigh -p MemoryMax -p MemorySwapMax -p OOMPolicy -p MemoryCurrent
; 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 í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.
- Figyelje néhány napon át az összes FPM-folyamat tényleges memóriaigényét, a terhelési csúcsok idején is.
- Állapítsa meg egy worker tipikus igényét, és szorozza meg a szolgáltatás összes poolja
pm.max_childrenértékével. - Tervezzen felárat a master folyamatra, az OPcache-re és a csúcsokra.
- A
MemoryHigh=értéket a mért csúcsérték fölé, kissé szorosan állítsa be, aMemoryMax=értéket némi távolsággal fölé. - Egy hét után igazítsa az értékeket a mérések és az OOM-események alapján.
# 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 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.
# 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.
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 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 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 amemory_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 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.