Aktuální situace: PHP2Shell. Dvě kritické zranitelnosti PHP (CVSS 9.2) umožňují spustit škodlivý kód bez přihlášení. Záplaty od 21. 10. 2026.Co nyní udělat →

OPcache vysvětlena: bytecode cache v PHP

OPcache drží přeložený kód PHP ve sdílené paměti. Šetří to výpočetní čas, vyžaduje ale pečlivost při nasazování, restartech a na serverech s více zákazníky.

Stav 4 min čteníZnalosti o PHP

Stručně: OPcache je vestavěná bytecode cache PHP. Podle příručky ukládá předkompilovaný bytecode do sdílené paměti, takže PHP nemusí skripty při každém požadavku znovu načítat a překládat. Je součástí dodávky od PHP 5.5.0. OPcache PHP zrychluje, ale nenahrazuje aktualizaci: po záplatě PHP je nutné restartovat všechny procesy PHP, nestačí vyprázdnit cache.

Co přesně OPcache dělá?

Při každém požadavku musí PHP skript přečíst, rozložit a přeložit do opcodů, tedy do příkazů pro virtuální stroj Zend Engine. U CMS se stovkami souborů je to hodně práce, která se neustále opakuje.

OPcache ukládá výsledek tohoto překladu do sdílené paměti (shared memory). Přistupují k ní všichni workeři služby PHP-FPM nebo všechny procesy Apache s mod_php. Pokud se soubor nezmění, jeho bytecode se použije přímo.

OPcache se načítá jako rozšíření Zend, nikoli jako běžné rozšíření:

; Linux (cesta podle balíčku)
zend_extension=opcache.so
; Windows
; zend_extension=php_opcache.dll

Podle příručky se má OPcache načítat před Xdebugem, pokud jsou aktivní oba.

Důležité je, komu sdílená paměť patří. U PHP-FPM ji vytváří hlavní proces (master) a využívají ji všichni workeři všech poolů této služby. U mod_php patří k hlavnímu procesu Apache. Restart služby proto cache vyprázdní úplně, jeden nový worker však ne. V příkazové řádce neexistuje sdílená paměť napříč voláními, protože každé volání je samostatný proces; tam je OPcache standardně vypnuta.

Pro rozhodovatele stačí jednoduché pravidlo: OPcache je na produkčních serverech téměř vždy užitečná, vyžaduje ale jasný postup pro nasazování a aktualizace.

Která nastavení OPcache jsou důležitá?

Následující hodnoty pocházejí ze stránky o konfiguraci v příručce PHP. Sloupec „Měnitelné“ ukazuje, kde lze nastavení provést: INI_SYSTEM jen v php.ini nebo v konfiguraci serveru, INI_ALL všude.

Direktiva Výchozí Měnitelné Význam
opcache.enable 1 INI_ALL cache zapnuta nebo vypnuta, za běhu lze jen vypnout
opcache.enable_cli 0 INI_SYSTEM cache pro příkazovou řádku
opcache.memory_consumption 128 INI_SYSTEM velikost sdílené paměti v MB
opcache.interned_strings_buffer 8 INI_SYSTEM paměť pro sdílené řetězce v MB
opcache.max_accelerated_files 10000 INI_SYSTEM maximální počet skriptů v cache
opcache.validate_timestamps 1 INI_ALL kontroluje, zda se soubory změnily
opcache.revalidate_freq 2 INI_ALL interval kontroly v sekundách, 0 = při každém požadavku
opcache.restrict_api prázdné INI_SYSTEM povoluje funkce API jen z jedné cesty
opcache.validate_permission 0 INI_SYSTEM kontroluje oprávnění k souborům vůči aktuálnímu uživateli
opcache.validate_root 0 INI_SYSTEM zabraňuje kolizím názvů při chroot
opcache.file_cache prázdné INI_SYSTEM druhá úroveň cache na disku

Typická produkční konfigurace by mohla vypadat takto. Hodnoty předem ověřte se svou aplikací:

opcache.enable=1
opcache.memory_consumption=256
opcache.interned_strings_buffer=16
opcache.max_accelerated_files=20000
opcache.validate_timestamps=1
opcache.revalidate_freq=60
opcache.restrict_api=/var/www/admin-tools

Kdo nastaví opcache.validate_timestamps=0, získá trochu výkonu. OPcache pak ale změněné soubory už vůbec nepozná a každé nasazení vyžaduje reset cache nebo restart.

Sledování cache a cílené vyprazdňování

OPcache má vlastní funkce, mimo jiné opcache_get_status(), opcache_get_configuration(), opcache_invalidate() a opcache_reset(). Krátký pohled jen pro čtení na naplnění:

<?php
$status = opcache_get_status(false);
if ($status === false) {
    exit("OPcache ist nicht aktiv.\n");
}
printf("Gecachte Skripte: %d\n", $status['opcache_statistics']['num_cached_scripts']);
printf("Freier Speicher: %.1f MB\n", $status['memory_usage']['free_memory'] / 1048576);

Na serverech s více weby by neměla mít každá aplikace možnost vyprazdňovat nebo číst cache všech ostatních. K tomu slouží opcache.restrict_api: funkce API smějí volat jen skripty pod zadanou cestou.

JIT: kompilátor strojového kódu v OPcache

Od PHP 8.0 obsahuje OPcache kompilátor JIT, který překládá opcody na strojový kód. Podle RFC k JIT je téměř samostatnou součástí OPcache a vytvořený kód ukládá do vlastní oblasti sdílené paměti. Řídí se pomocí opcache.jit a opcache.jit_buffer_size. Od PHP 8.4.0 je opcache.jit standardně nastaveno na disable. Kdy se JIT vyplatí, vysvětluje článek JIT a výkon v PHP 8.

OPcache a bezpečnost: co platí po PHP2Shell

OPcache není bezpečnostní nástroj, má ale důsledky pro bezpečnost. Po PHP2Shell jsou důležité tři body:

  1. Reset cache není aktualizace. opcache_reset() vyprázdní jen skripty v cache. Interpret se zranitelnostmi CVE-2026-109618 a CVE-2026-109619 zůstává v paměti, dokud nejsou restartovány všechny procesy. Jak na to, popisuje článek Restart PHP-FPM a všech workerů.
  2. Vložený kód může v cache přežít. Pokud byl soubor zmanipulován a později nahrazen, může se při vypnuté kontrole časových razítek dál provádět stará verze. Po vyčištění proto patří k postupu restart.
  3. Sdílená paměť vyžaduje oddělení. Na serverech s více zákazníky pomáhají samostatné pooly PHP-FPM pro každý web a také opcache.validate_permission a opcache.restrict_api. Adresář pro opcache.file_cache smí být zapisovatelný jen pro uživatele PHP.
Tip

Po každé aktualizaci zkontrolujte, zda je doba spuštění procesů PHP později než aktualizace. Plná OPcache s vysokou úspěšností není důkazem, že běží nový interpret.

Jak konkrétně pomáhá PHP SOS?

  • Zkontrolovat konfiguraci: Načteme aktivní konfiguraci OPcache pro každý provozní režim a porovnáme ji s vaší aplikací.
  • Zabezpečit nasazování: Zavedeme pevný postup pro reset cache a restart, aby nepokračovala žádná stará verze kódu.
  • Oddělit klienty: V rámci zpevnění serveru nastavíme oddělené pooly, restrict_api a vhodná oprávnění.
  • Kontrolovat po aktualizacích: Podle časů spuštění procesů doložíme, že aktualizovaný interpret skutečně běží.

Časté dotazy

Je OPcache standardně aktivní?

OPcache se s PHP dodává od PHP 5.5.0 a podle příručky běží s výchozím nastavením opcache.enable=1, jakmile je rozšíření načteno. Zda je načteno, závisí na vašem balíčku nebo poskytovateli hostingu. V příkazové řádce je OPcache naopak standardně vypnuta (opcache.enable_cli=0).

Proč po nasazení stále vidím starý kód?

Pravděpodobně OPcache kontroluje změny souborů jen v intervalech, nebo vůbec. S opcache.revalidate_freq čeká standardně dvě sekundy, s opcache.validate_timestamps=0 nikdy. Pak pomůže jen reset cache nebo restart PHP-FPM, resp. Apache.

Stačí po aktualizaci PHP opcache_reset()?

Ne. opcache_reset() vyprázdní jen cache s přeloženými skripty. Aktualizace PHP nahrazuje samotný interpret a ten je načten v každém běžícím procesu. K tomu je nutné restartovat všechny procesy PHP.

Je JIT v PHP 8.4 zapnutý?

Podle příručky je opcache.jit od PHP 8.4.0 standardně nastaveno na disable, zatímco opcache.jit_buffer_size činí 64M. Dříve to bylo naopak: jit na tracing, vyrovnávací paměť na 0. V obou případech není JIT bez vědomé konfigurace aktivní.

Zdroje

Okamžitý kontakt

Každá hodina se počítá. Napište nám hned.

Stručně popište systém, verzi PHP a pozorování. Ozveme se, vyjasníme situaci a budeme pracovat na dálku, dokud nebude incident uzavřen a zdokumentován.

Okamžitá pomoc