Cache de GLPI : pourquoi votre modification n'apparaît pas

GLPI conserve trois caches distincts et les boutons de vidage n'apparaissent qu'en mode débogage. Voyez lequel vider selon le symptôme, sur GLPI 10, 11 et 12.

Vous avez mis à jour un plugin, corrigé une traduction ou modifié un paramètre, et l'écran reste identique. La plupart du temps, le problème ne vient pas de ce que vous avez changé, mais du cache de GLPI, qui continue de servir la version précédente.

GLPI n'a pas "un cache". Il en a trois.

C'est le premier point qui prête à confusion. Quand quelqu'un dit "videz le cache de GLPI", il y a trois choses différentes derrière, avec des finalités distinctes, et vider la mauvaise ne résout rien :

  • Cache d'opcode (PHP) : il conserve le bytecode des fichiers .php déjà compilés, pour que PHP ne réinterprète pas le code à chaque requête. C'est l'extension Zend OPcache, de PHP lui-même, pas de GLPI.
  • Cache de données utilisateur : il conserve des données de l'application, comme les paramètres et les listes que GLPI consulte en permanence. En interne, GLPI appelle ce contexte core, et il peut résider sur disque ou dans Redis/Memcached.
  • Cache de traduction : il conserve les catalogues de langue déjà traités, pour que GLPI ne lise pas les fichiers .mo à chaque écran. C'est le responsable du symptôme le plus fréquent, le texte qui reste dans l'ancienne langue.

La règle pratique : si ce qui a changé est du code, le suspect est l'opcode. S'il s'agit de texte d'interface, c'est celui des traductions. Si c'est une configuration ou une donnée, c'est celui des données utilisateur.

Où se trouvent ces fichiers

Le cache sur disque de GLPI se trouve dans le dossier de fichiers de l'installation, sous files/_cache/. À l'intérieur, vous trouverez un répertoire dont le nom ressemble à ceci :

files/_cache/11.0.7-49a93008-production/
    app/
    templates/
    translations/

Un avertissement sur ces trois dossiers : ils ne correspondent pas un pour un aux trois caches affichés à l'écran. Le dossier translations contient bien les catalogues de langue, mais app est le cache interne du framework (conteneur d'injection de dépendances, annotations), et non le cache de données utilisateur. Et si l'environnement est configuré avec Redis ou Memcached, les données utilisateur ne sont pas du tout dans ce répertoire : elles vivent dans le service externe, tandis que le dossier sur disque continue d'exister avec le cache du framework. Chercher là, dans ce cas, mène au mauvais endroit.

Observez le nom du dossier : il porte la version de GLPI, un hash et l'environnement. Cela a une conséquence pratique peu connue : lors d'une mise à jour de GLPI, l'espace de noms change et l'ancien cache cesse d'être consulté de lui-même. C'est pourquoi une montée de version souffre rarement d'un cache obsolète, alors que la mise à jour d'un plugin, qui ne change pas la version de GLPI, en souffre souvent.

Attention si vous êtes sur GLPI 10 : cette organisation en un répertoire unique versionné appartient à la ligne 11 et 12, qui reposent sur le Kernel Symfony. Dans GLPI 10, le même files/_cache a une autre structure, avec des dossiers séparés et sans suffixe d'environnement :

files/_cache/core/
files/_cache/templates/
files/_cache/installer-10.0.24/
files/_cache/translations-10.0.24/

Notez que seuls l'installateur et les traductions portent la version dans le nom, et que les anciennes versions s'accumulent : il est courant de trouver une demi-douzaine de translations-10.0.x issus de mises à jour passées. Les chemins changent, mais le raisonnement de cet article reste le même, et les boutons de l'interface comme la commande console fonctionnent de façon identique.

Les plugins utilisent aussi ce répertoire. Dans une installation avec NexTool, par exemple, on y trouve des fichiers comme nextool_boot_manifest.cache ainsi que des entrées par module, chacune avec sa propre stratégie d'invalidation.

Disque ou Redis : où se trouve réellement votre cache

Le cache de données utilisateur et celui des traductions ne sont pas nécessairement sur disque. GLPI permet de les diriger vers Redis ou Memcached, et l'écran Performance indique lui-même quel système est utilisé, avec une ligne du type "L'extension de cache redis est installée" ou "Le système de cache filesystem est utilisé".

Cela change le diagnostic dans deux cas fréquents. Dans une installation avec plusieurs serveurs applicatifs derrière un répartiteur de charge, un cache sur disque signifie un cache par serveur : le vider sur un nœud ne le vide pas sur les autres, et l'utilisateur voit l'ancien ou le nouveau contenu selon le serveur qui a traité sa requête. Avec un Redis partagé, en revanche, un seul vidage vaut pour tous.

L'autre cas est le conteneur. Si le cache est sur disque à l'intérieur du conteneur et non dans un volume, recréer le conteneur vide le cache au passage, ce qui parfois "résout" le problème par accident et masque la cause réelle.

Pour vérifier ou modifier la configuration en ligne de commande :

php bin/console cache:configure

Les plugins ont aussi un cache

Au-delà des trois caches du cœur, chaque plugin peut conserver le sien. GLPI propose un contexte dédié par plugin, et c'est pour cela que la commande de vidage accepte --context=plugin:nom_du_plugin.

Une réserve s'impose : ce contexte n'existe que si le plugin utilise l'API de cache de GLPI. De nombreux plugins conservent leur cache dans des fichiers isolés, en dehors de ce mécanisme, et dans ces cas --context=plugin:nom n'a aucun effet sur eux. Si le comportement persiste après avoir tout vidé, cherchez les fichiers de cache propres au plugin dans le répertoire files/_cache.

En pratique, cela signifie qu'un comportement étrange après la mise à jour d'un plugin ne se résout pas toujours en vidant les caches de GLPI : il peut être nécessaire de vider le contexte de ce plugin précisément. Les plugins comportant de nombreux modules conservent souvent en cache des manifestes d'initialisation et des schémas, justement pour ne pas tout recalculer à chaque requête, et c'est ce fichier qui devient obsolète après un changement de version.

Pourquoi les boutons de vidage n'apparaissent pas

Voici le détail qui conduit beaucoup de monde à conclure que l'option n'existe pas dans leur version. L'écran est là, les blocs sont là, et pourtant aucun bouton à cliquer.

La raison est que les boutons de vidage ne s'affichent que lorsque l'utilisateur est en mode débogage. Dans le code de GLPI 11, chacun des trois blocs se trouve dans une condition qui vérifie le mode de la session. En mode normal, l'écran affiche le diagnostic, la mémoire, le taux de succès, l'extension utilisée, mais n'offre pas l'action.

Autrement dit : ce ne sont pas les droits, ce n'est pas la version, ce n'est pas un bogue. C'est le mode de la session.

Comment activer le mode débogage

Le mode se trouve dans le profil de l'utilisateur, et non dans un paramètre global :

  1. Cliquez sur votre nom, en haut à droite, et ouvrez les Préférences.
  2. Repérez le champ Utiliser GLPI en mode.
  3. Passez de Normal à Débogage et enregistrez.
Écran des préférences de GLPI avec le champ Utiliser GLPI en mode mis en évidence, où l'on passe de Normal à Débogage
Le champ se situe au milieu des préférences de l'utilisateur, juste sous la langue, et n'apparaît que pour les profils administratifs.

Deux remarques importantes. La première : ce champ n'apparaît que pour les utilisateurs ayant un profil administrateur. Si vous ne le trouvez pas, la marche à suivre est de le demander à un administrateur de l'environnement. La seconde : le mode débogage fait afficher à GLPI des informations techniques sur plusieurs écrans et ajoute une surcharge de traitement. Revenez en mode Normal dès que vous avez terminé, surtout en production.

Vider depuis l'interface

Le mode débogage activé, allez dans Configuration > Général et ouvrez l'onglet Performance. Les trois blocs affichent désormais chacun leur bouton de vidage, chacun ne vidant que son propre cache.

Si les boutons n'apparaissent toujours pas après l'enregistrement de la préférence, rechargez la page de configuration. L'onglet performance charge son contenu de façon asynchrone, et il a pu être rendu avant le changement de mode.

Onglet Performance de GLPI montrant les trois blocs de cache, chacun avec son bouton de vidage
Avec le mode débogage actif, chaque bloc dispose de son propre bouton de vidage.

Ne videz que le bloc correspondant à votre symptôme. Vider les trois "par précaution" est une habitude coûteuse : supprimer le cache d'opcode oblige PHP à recompiler toute l'application lors des requêtes suivantes, et dans un environnement avec des utilisateurs actifs cela se traduit par des lenteurs pendant quelques minutes.

Vider en ligne de commande

Qui dispose d'un accès au serveur bénéficie d'une voie plus directe, qui n'exige ni le mode débogage ni le passage par l'interface. Depuis la racine de l'installation de GLPI :

# vide tous les contextes de cache
php bin/console cache:clear

La commande accepte de restreindre la portée, ce qui est préférable en production pour la même raison que ci-dessus :

# vide uniquement le cache de traduction, le cas le plus courant
php bin/console cache:clear --context=translations

# vide uniquement les données utilisateur
php bin/console cache:clear --context=core

# vide le cache d'un plugin précis
php bin/console cache:clear --context=plugin:nom_du_plugin

Une précaution qui évite bien des ennuis : exécutez la commande avec le même utilisateur que celui du serveur web (généralement www-data ou apache). L'exécuter en root recrée des fichiers de cache appartenant à root, le serveur web ne peut alors plus y écrire, et un problème temporaire devient permanent.

À noter que cache:clear agit sur les caches gérés par GLPI. Le cache d'opcode de PHP appartient à l'extension elle-même, et il est réinitialisé au rechargement du service PHP-FPM.

Lequel vider selon le symptôme

Ce qui se passeCache à vider
Le texte reste dans l'ancienne langue après la mise à jour d'un pluginTraduction
Une nouvelle traduction ajoutée n'apparaît pasTraduction
Une modification dans un fichier .php reste sans effetOpcode (PHP)
Paramètre enregistré mais l'écran affiche l'ancienne valeurDonnées utilisateur
Menu ou entrée de plugin qui persiste après la désinstallationDonnées utilisateur

Et dans GLPI 12 ?

En comparant le code des deux versions, la méthode décrite ici reste entièrement valable dans GLPI 12 : les mêmes trois caches, les mêmes contextes core et translations, la même exigence de mode débogage pour que les boutons apparaissent, et la même commande console. Le répertoire sur disque suit le schéma de la ligne 11, avec la version dans le nom, comme dans files/_cache/12.0.0-rc1-08464f22-production/.

Deux différences méritent l'attention de qui administre des environnements comportant de nombreux plugins.

La première concerne la mémoire. Dans GLPI 12, le vidage du cache ignore désormais la précompilation des gabarits, avec une justification explicite dans le code lui-même : il y a plus de 400 gabarits, et tous les préchauffer d'un coup dépassait la limite de mémoire par défaut de PHP. À la place, chaque gabarit est compilé la première fois que sa page est ouverte. En pratique, le vidage devient plus léger et plus fiable, mais le coût est reporté sur celui qui ouvre chaque écran en premier après l'opération.

La seconde concerne les plugins. Dans GLPI 12, activer, désactiver ou installer n'importe quel plugin vide désormais l'intégralité du cache des gabarits compilés, et pas seulement celui de ce plugin. Le code lui-même consigne cette limite, avec une note demandant de séparer à l'avenir le cache par espace de noms. L'effet de bord est que, dans un environnement riche en modules, toucher à un seul plugin fait recompiler tous les gabarits à la demande ensuite. Rien ne casse, mais les premiers affichages sont plus lents.

Le cas qui trompe : la moitié de l'écran traduite

Il existe une situation où le cache de traduction trompe même ceux qui connaissent bien le système. L'écran s'ouvre avec une partie des textes dans la bonne langue et une partie dans la langue d'origine, mélangés, parfois dans des champs voisins. La conclusion naturelle est que la traduction du plugin est incomplète.

Presque toujours, elle ne l'est pas. Lorsqu'un plugin se met à jour tout seul et écrase ses propres fichiers, il doit invalider deux caches, et non un : celui d'opcode, pour que PHP exécute le nouveau code, et celui des traductions, pour que GLPI relise les catalogues. N'invalider que le premier produit exactement ce résultat : les chaînes déjà existantes continuent d'être servies depuis le cache, traduites, tandis que les nouvelles chaînes de cette version ne sont pas encore dans le catalogue en mémoire et s'affichent dans la langue source.

Ce qui trahit le cas, c'est précisément le mélange. Une traduction réellement incomplète laisse généralement des blocs entiers dans la langue d'origine, en suivant la structure du fichier de traduction. Un cache obsolète laisse l'ancien texte traduit et le nouveau non, sans logique apparente, car la séparation ne se fait pas par écran : elle se fait selon ce qui était déjà en mémoire.

La confirmation est simple : videz le cache de traduction et rechargez. Si l'écran devient cohérent, c'était le cache. Si le mélange persiste, il vaut alors la peine d'examiner le catalogue de langue de cette version.

Précautions en production

Trois recommandations valables pour tout environnement où des utilisateurs travaillent :

  • Préférez le cache spécifique plutôt que de tout vider. Le symptôme désigne presque toujours un seul d'entre eux.
  • Évitez les heures de pointe pour vider l'opcode, et dans GLPI 12 également pour le vidage général, puisque les gabarits sont alors compilés au premier accès à chaque écran. La recompilation se fait à la demande, le coût retombe donc précisément sur ceux qui utilisent le système à ce moment-là.
  • Ne laissez pas le mode débogage activé. Outre la surcharge, il expose à l'écran des détails techniques de l'environnement.

Quand le problème n'est pas le cache

Si vous avez vidé le bon cache et que le comportement persiste, deux points méritent d'être vérifiés avant d'aller plus loin. D'abord, si la modification est réellement parvenue au serveur : pour les plugins, confirmez la version installée, et non la version publiée. Ensuite, si votre langue dispose d'un catalogue : si le plugin traduit vers es_ES et que votre profil utilise une variante régionale sans catalogue propre, GLPI retombe sur le texte d'origine.


Revu par l'équipe NexTool Solutions.

Questions fréquentes

Non. Un cache est une copie temporaire de quelque chose que GLPI sait reconstruire. Les paramètres, tickets, actifs et règles se trouvent dans la base de données et ne sont pas affectés. Le seul effet de bord est une lenteur passagère pendant la reconstruction.

Il n'existe pas de routine recommandée. Le cache n'est pas quelque chose que l'on vide périodiquement par hygiène ; il s'invalide de lui-même dans la plupart des cas. Videz-le lorsqu'un symptôme concret se présente, et seulement le cache concerné.

Pour les caches gérés par GLPI, non. Pour le cache d'opcode de PHP, le bouton de l'interface s'en charge dans la plupart des installations ; dans les environnements où PHP tourne dans un processus séparé, recharger le service PHP-FPM produit le même effet.

Si l'ancien texte est réapparu, le cache a été reconstruit à partir de la même source obsolète. Dans ce cas, le problème n'est pas le cache, mais le fichier de traduction sur le serveur, et il convient de vérifier si la version installée du plugin est bien celle qui apporte la correction.

Besoin d'aide ?