Situation actuelle : PHP2Shell. Deux failles PHP critiques (CVSS 9.2) permettent d'exécuter du code malveillant sans authentification. Correctifs disponibles depuis le 21 octobre 2026.Ce qu'il faut faire maintenant →

OPcache expliqué : le cache de bytecode de PHP

OPcache conserve le code PHP traduit dans la mémoire partagée. Cela économise du temps de calcul, mais exige de la rigueur lors des déploiements, des redémarrages et sur les serveurs multi-clients.

État 5 min de lectureSavoir PHP

En bref : OPcache est le cache de bytecode intégré de PHP. Selon le manuel, il stocke du bytecode précompilé dans la mémoire partagée, de sorte que PHP n'a pas à recharger et à retraduire les scripts à chaque requête. Il est livré avec PHP depuis PHP 5.5.0. OPcache rend PHP plus rapide, mais ne remplace pas une mise à jour : après un correctif PHP, tous les processus PHP doivent redémarrer, il ne suffit pas de vider le cache.

Que fait exactement OPcache ?

À chaque requête, PHP doit lire un script, le décomposer et le traduire en opcodes, c'est-à-dire en instructions pour la machine virtuelle de la Zend Engine. Pour un CMS de plusieurs centaines de fichiers, c'est beaucoup de travail qui se répète sans cesse.

OPcache stocke le résultat de cette traduction dans la mémoire partagée (shared memory). Tous les workers d'un service PHP-FPM ou tous les processus Apache avec mod_php y accèdent. Si un fichier ne change pas, son bytecode est réutilisé directement.

OPcache se charge comme extension Zend, et non comme extension ordinaire :

; Linux (chemin selon le paquet)
zend_extension=opcache.so
; Windows
; zend_extension=php_opcache.dll

Selon le manuel, OPcache doit être chargé avant Xdebug lorsque les deux sont actifs.

Il importe de savoir à qui appartient la mémoire partagée. Avec PHP-FPM, le processus maître la crée et tous les workers de tous les pools de ce service l'utilisent. Avec mod_php, elle appartient au processus principal d'Apache. Un redémarrage du service vide donc entièrement le cache, alors qu'un simple nouveau worker ne le fait pas. En ligne de commande, il n'existe pas de mémoire partagée d'un appel à l'autre, car chaque appel est un processus distinct ; OPcache y est désactivé par défaut.

Pour les décideurs, une règle simple suffit : OPcache est presque toujours pertinent sur les serveurs de production, mais exige une procédure claire pour les déploiements et les mises à jour.

Quels réglages d'OPcache comptent ?

Les valeurs suivantes proviennent de la page de configuration du manuel PHP. La colonne « Modifiable » indique où un réglage peut être défini : INI_SYSTEM uniquement dans php.ini ou la configuration du serveur, INI_ALL partout.

Directive Par défaut Modifiable Signification
opcache.enable 1 INI_ALL cache activé ou désactivé, à l'exécution uniquement désactivable
opcache.enable_cli 0 INI_SYSTEM cache pour la ligne de commande
opcache.memory_consumption 128 INI_SYSTEM taille de la mémoire partagée en Mo
opcache.interned_strings_buffer 8 INI_SYSTEM mémoire pour les chaînes partagées en Mo
opcache.max_accelerated_files 10000 INI_SYSTEM nombre maximal de scripts en cache
opcache.validate_timestamps 1 INI_ALL vérifie si les fichiers ont été modifiés
opcache.revalidate_freq 2 INI_ALL intervalle de vérification en secondes, 0 = à chaque requête
opcache.restrict_api vide INI_SYSTEM n'autorise les fonctions de l'API qu'à partir d'un chemin
opcache.validate_permission 0 INI_SYSTEM vérifie les droits sur les fichiers par rapport à l'utilisateur courant
opcache.validate_root 0 INI_SYSTEM évite les collisions de noms avec chroot
opcache.file_cache vide INI_SYSTEM deuxième niveau de cache sur le disque

Une configuration de production typique pourrait ressembler à ceci. Vérifiez au préalable les valeurs avec votre application :

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

Avec opcache.validate_timestamps=0, on gagne un peu de performance. Mais OPcache ne détecte alors plus du tout les fichiers modifiés, et chaque déploiement exige une réinitialisation du cache ou un redémarrage.

Observer le cache et le vider de façon ciblée

OPcache fournit ses propres fonctions, dont opcache_get_status(), opcache_get_configuration(), opcache_invalidate() et opcache_reset(). Un bref coup d'œil, en lecture seule, au taux de remplissage :

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

Sur les serveurs hébergeant plusieurs sites, chaque application ne devrait pas pouvoir vider ou lire le cache de toutes les autres. C'est à cela que sert opcache.restrict_api : seuls les scripts situés sous le chemin indiqué peuvent appeler les fonctions de l'API.

JIT : le compilateur de code machine dans OPcache

Depuis PHP 8.0, OPcache contient un compilateur JIT qui traduit les opcodes en code machine. Selon le RFC sur le JIT, il constitue une partie presque autonome d'OPcache et place le code produit dans une zone distincte de la mémoire partagée. Il se pilote avec opcache.jit et opcache.jit_buffer_size. Depuis PHP 8.4.0, opcache.jit vaut disable par défaut. L'article JIT et performances dans PHP 8 explique quand le JIT vaut la peine.

OPcache et sécurité : ce qui s'applique après PHP2Shell

OPcache n'est pas un outil de sécurité, mais il a des conséquences pour la sécurité. Trois points comptent après PHP2Shell :

  1. Une réinitialisation du cache n'est pas une mise à jour. opcache_reset() ne vide que les scripts en cache. L'interpréteur affecté par les failles CVE-2026-109618 et CVE-2026-109619 reste en mémoire jusqu'au redémarrage de tous les processus. La marche à suivre figure sous Redémarrer PHP-FPM et tous les workers.
  2. Du code injecté peut survivre dans le cache. Si un fichier a été manipulé puis remplacé, l'ancienne version peut continuer à s'exécuter lorsque la vérification des horodatages est désactivée. Après un nettoyage, un redémarrage est donc nécessaire.
  3. La mémoire partagée exige une séparation. Sur les serveurs multi-clients, des pools PHP-FPM distincts par site ainsi que opcache.validate_permission et opcache.restrict_api aident. Un répertoire pour opcache.file_cache ne doit être accessible en écriture que par l'utilisateur PHP.
Astuce

Après chaque mise à jour, vérifiez que l'heure de démarrage des processus PHP est postérieure à la mise à jour. Un OPcache plein avec un taux de réussite élevé ne prouve pas que le nouvel interpréteur tourne.

Comment PHP SOS aide-t-il concrètement ?

  • Vérifier la configuration : nous relevons la configuration d'OPcache active pour chaque mode d'exécution et la comparons à votre application.
  • Sécuriser les déploiements : nous mettons en place une procédure fixe de réinitialisation du cache et de redémarrage, afin qu'aucune ancienne version du code ne continue de tourner.
  • Séparer les clients : dans le cadre du durcissement de serveur, nous configurons des pools distincts, restrict_api et des droits adaptés.
  • Contrôler après les mises à jour : nous prouvons, grâce aux heures de démarrage des processus, que l'interpréteur mis à jour est réellement actif.

Questions fréquentes

OPcache est-il actif par défaut ?

OPcache est livré avec PHP depuis PHP 5.5.0 et, selon le manuel, fonctionne par défaut avec opcache.enable=1 dès que l'extension est chargée. Qu'elle soit chargée dépend de votre paquet ou de votre hébergeur. En ligne de commande, en revanche, OPcache est désactivé par défaut (opcache.enable_cli=0).

Pourquoi vois-je encore l'ancien code après un déploiement ?

Vraisemblablement parce qu'OPcache ne vérifie les modifications de fichiers qu'à intervalles réguliers, voire jamais. Avec opcache.revalidate_freq, il attend par défaut deux secondes ; avec opcache.validate_timestamps=0, jamais. Seule une réinitialisation du cache ou un redémarrage de PHP-FPM ou d'Apache aide alors.

opcache_reset() suffit-il après une mise à jour de PHP ?

Non. opcache_reset() ne vide que le cache des scripts traduits. Une mise à jour de PHP remplace l'interpréteur lui-même, qui est chargé dans chaque processus en cours d'exécution. Pour cela, tous les processus PHP doivent être redémarrés.

Le JIT est-il activé dans PHP 8.4 ?

Selon le manuel, opcache.jit est réglé sur disable par défaut depuis PHP 8.4.0, tandis que opcache.jit_buffer_size vaut 64M. Auparavant, c'était l'inverse : jit sur tracing, tampon à 0. Dans les deux cas, le JIT n'est pas actif sans configuration délibérée.

Sources

Contact immédiat

Chaque heure compte. Écrivez-nous maintenant.

Décrivez brièvement votre système, votre version de PHP et ce que vous avez observé. Nous vous répondons, faisons le point et travaillons à distance jusqu'à la clôture et la documentation de l'incident.

Aide immédiate