Ajankohtainen tilanne: PHP2Shell. Kaksi kriittistä PHP-haavoittuvuutta (CVSS 9.2) sallii haittakoodin suorittamisen ilman kirjautumista. Korjaukset 21.10.2026 alkaen.Mitä nyt on tehtävä →

OPcache selitettynä: PHP:n tavukoodivälimuisti

OPcache pitää käännetyn PHP-koodin jaetussa muistissa. Se säästää laskenta-aikaa, mutta vaatii huolellisuutta käyttöönotoissa, uudelleenkäynnistyksissä ja usean asiakkaan palvelimilla.

Tilanne Lukuaika 4 minPHP-tietoa

Lyhyesti: OPcache on PHP:n sisäänrakennettu tavukoodivälimuisti. Käsikirjan mukaan se tallentaa esikäännettyä tavukoodia jaettuun muistiin, jolloin PHP:n ei tarvitse ladata ja kääntää komentosarjoja uudelleen jokaisella pyynnöllä. Se kuuluu toimitukseen versiosta PHP 5.5.0 lähtien. OPcache nopeuttaa PHP:tä, mutta ei korvaa päivitystä: PHP-korjauksen jälkeen kaikki PHP-prosessit on käynnistettävä uudelleen, välimuistin tyhjennys ei riitä.

Mitä OPcache tarkalleen tekee?

Jokaisella pyynnöllä PHP:n on luettava komentosarja, pilkottava se ja käännettävä opcode-käskyiksi eli Zend Enginen virtuaalikoneen komennoiksi. Sadoista tiedostoista koostuvassa CMS-järjestelmässä se on paljon työtä, joka toistuu jatkuvasti.

OPcache tallentaa tämän käännöksen tuloksen jaettuun muistiin (shared memory). Kaikki PHP-FPM-palvelun worker-prosessit tai kaikki mod_php:tä käyttävät Apache-prosessit käyttävät sitä. Jos tiedosto ei muutu, sen tavukoodia käytetään suoraan uudelleen.

OPcache ladataan Zend-laajennuksena, ei tavallisena laajennuksena:

; Linux (polku paketista riippuen)
zend_extension=opcache.so
; Windows
; zend_extension=php_opcache.dll

Käsikirjan mukaan OPcache tulee ladata ennen Xdebugia, jos molemmat ovat aktiivisia.

On tärkeää tietää, kenelle jaettu muisti kuuluu. PHP-FPM:ssä master-prosessi luo sen, ja tämän palvelun kaikkien poolien kaikki worker-prosessit käyttävät sitä. mod_php:ssä se kuuluu Apachen pääprosessille. Palvelun uudelleenkäynnistys tyhjentää siksi välimuistin kokonaan, mutta yksittäinen uusi worker ei. Komentorivillä ei ole kutsujen yli ulottuvaa jaettua muistia, koska jokainen kutsu on oma prosessinsa; siellä OPcache on oletuksena pois päältä.

Päättäjälle riittää nyrkkisääntö: OPcache on tuotantopalvelimilla lähes aina järkevä, mutta se vaatii selkeän toimintatavan käyttöönotoille ja päivityksille.

Mitkä OPcache-asetukset ovat tärkeitä?

Seuraavat arvot ovat PHP-käsikirjan konfiguraatiosivulta. Sarake ”Muutettavissa” näyttää, missä asetuksen saa asettaa: INI_SYSTEM vain php.ini-tiedostossa tai palvelinkonfiguraatiossa, INI_ALL missä tahansa.

Direktiivi Oletus Muutettavissa Merkitys
opcache.enable 1 INI_ALL välimuisti päälle tai pois, ajon aikana vain sammutettavissa
opcache.enable_cli 0 INI_SYSTEM välimuisti komentoriville
opcache.memory_consumption 128 INI_SYSTEM jaetun muistin koko megatavuina
opcache.interned_strings_buffer 8 INI_SYSTEM yhteisten merkkijonojen muisti megatavuina
opcache.max_accelerated_files 10000 INI_SYSTEM välimuistiin tallennettavien komentosarjojen enimmäismäärä
opcache.validate_timestamps 1 INI_ALL tarkistaa, onko tiedostoja muutettu
opcache.revalidate_freq 2 INI_ALL tarkistusväli sekunteina, 0 = jokaisella pyynnöllä
opcache.restrict_api tyhjä INI_SYSTEM sallii API-funktiot vain tietystä polusta
opcache.validate_permission 0 INI_SYSTEM tarkistaa tiedosto-oikeudet nykyistä käyttäjää vasten
opcache.validate_root 0 INI_SYSTEM estää nimikolliosiot chroot-ympäristössä
opcache.file_cache tyhjä INI_SYSTEM toinen välimuistitaso levyllä

Tyypillinen tuotantokonfiguraatio voisi näyttää tältä. Tarkistakaa arvot ensin omalla sovelluksellanne:

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

Jos asettaa opcache.validate_timestamps=0, saa hieman lisää suorituskykyä. Silloin OPcache ei kuitenkaan enää huomaa muuttuneita tiedostoja lainkaan, ja jokainen käyttöönotto vaatii välimuistin nollauksen tai uudelleenkäynnistyksen.

Välimuistin tarkkailu ja kohdennettu tyhjennys

OPcachessa on omat funktionsa, muun muassa opcache_get_status(), opcache_get_configuration(), opcache_invalidate() ja opcache_reset(). Lyhyt, vain lukeva katsaus täyttöasteeseen:

<?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);

Usean verkkosivuston palvelimilla ei pidä sallia, että jokainen sovellus voi tyhjentää tai lukea kaikkien muiden välimuistin. Tähän on tarkoitettu opcache.restrict_api: vain annetun polun alla olevat komentosarjat saavat kutsua API-funktioita.

JIT: OPcachen konekoodikääntäjä

PHP 8.0:sta lähtien OPcachessa on JIT-kääntäjä, joka kääntää opcodet konekoodiksi. JIT-RFC:n mukaan se on lähes itsenäinen osa OPcachea ja tallentaa tuottamansa koodin jaetun muistin omalle alueelleen. Sitä ohjataan asetuksilla opcache.jit ja opcache.jit_buffer_size. Versiosta PHP 8.4.0 lähtien opcache.jit on oletuksena disable. Milloin JIT kannattaa, selittää artikkeli JIT ja suorituskyky PHP 8:ssa.

OPcache ja tietoturva: mikä pätee PHP2Shellin jälkeen

OPcache ei ole tietoturvatyökalu, mutta sillä on vaikutuksia tietoturvaan. Kolme asiaa on PHP2Shellin jälkeen tärkeitä:

  1. Välimuistin nollaus ei ole päivitys. opcache_reset() tyhjentää vain välimuistissa olevat komentosarjat. Tulkki, jossa ovat haavoittuvuudet CVE-2026-109618 ja CVE-2026-109619, pysyy muistissa, kunnes kaikki prosessit on käynnistetty uudelleen. Miten se tehdään, kerrotaan sivulla PHP-FPM ja kaikkien worker-prosessien uudelleenkäynnistys.
  2. Lisätty koodi voi elää välimuistissa edelleen. Jos tiedostoa on manipuloitu ja se on myöhemmin korvattu, vanha versio voi aikaleimatarkistuksen ollessa pois päältä jatkaa suorittamista. Puhdistuksen jälkeen uudelleenkäynnistys kuuluu siksi asiaan.
  3. Jaettu muisti vaatii erottelua. Usean asiakkaan palvelimilla auttavat kullekin verkkosivustolle omat PHP-FPM-poolit sekä opcache.validate_permission ja opcache.restrict_api. Hakemisto asetukselle opcache.file_cache saa olla kirjoitettavissa vain PHP-käyttäjälle.
Vinkki

Tarkistakaa jokaisen päivityksen jälkeen, onko PHP-prosessien käynnistysaika päivityksen jälkeinen. Täysi OPcache ja korkea osumasuhde eivät todista, että uusi tulkki on käytössä.

Miten PHP SOS auttaa konkreettisesti?

  • Konfiguraation tarkistus: Luemme aktiivisen OPcache-konfiguraation ajotavoittain ja sovitamme sen sovellukseenne.
  • Käyttöönottojen turvaaminen: Otamme käyttöön kiinteän toimintatavan välimuistin nollaukselle ja uudelleenkäynnistykselle, jotta vanha koodiversio ei jää käyntiin.
  • Asiakkaiden erottelu: Palvelimen koventamisen puitteissa asetamme erilliset poolit, restrict_api-asetuksen ja sopivat oikeudet.
  • Tarkistus päivitysten jälkeen: Osoitamme prosessien käynnistysaikojen avulla, että päivitetty tulkki on todella aktiivinen.

Usein kysytyt kysymykset

Onko OPcache oletuksena päällä?

OPcache toimitetaan PHP:n mukana versiosta PHP 5.5.0 lähtien, ja käsikirjan mukaan sitä ajetaan oletuksena asetuksella opcache.enable=1, kun laajennus on ladattu. Se, onko laajennus ladattu, riippuu paketistanne tai hosting-yrityksestänne. Komentorivillä OPcache on sen sijaan oletuksena pois päältä (opcache.enable_cli=0).

Miksi näen käyttöönoton jälkeen yhä vanhan koodin?

Todennäköisesti OPcache tarkistaa tiedostomuutokset vain välein tai ei lainkaan. Asetuksella opcache.revalidate_freq se odottaa oletuksena kaksi sekuntia, asetuksella opcache.validate_timestamps=0 ei koskaan. Silloin auttaa vain välimuistin nollaus tai PHP-FPM:n tai Apachen uudelleenkäynnistys.

Riittääkö opcache_reset() PHP-päivityksen jälkeen?

Ei. opcache_reset() tyhjentää vain käännettyjen komentosarjojen välimuistin. PHP-päivitys korvaa itse tulkin, ja se on ladattuna jokaisessa käynnissä olevassa prosessissa. Siksi kaikki PHP-prosessit on käynnistettävä uudelleen.

Onko JIT päällä PHP 8.4:ssä?

Käsikirjan mukaan opcache.jit on versiosta PHP 8.4.0 lähtien oletuksena disable ja opcache.jit_buffer_size on 64M. Aiemmin tilanne oli päinvastainen: jit oli tracing ja puskuri 0. Kummassakin tapauksessa JIT ei ole aktiivinen ilman tietoista konfigurointia.

Lähteet

Pikayhteys

Jokainen tunti on tärkeä. Kirjoittakaa meille nyt.

Kuvatkaa lyhyesti järjestelmä, PHP-versio ja havainnot. Otamme yhteyttä, selvitämme tilanteen ja työskentelemme etänä, kunnes tapaus on käsitelty loppuun ja dokumentoitu.

Pikaapu