Les inodes perdues ! Cette semaine, j’ai eu droit à un problème particulier sur le serveur : alors que rien dans la configuration des services n’a été changé, je me suis rendu compte que WordPress ne réagissait pas comme d’habitude.
Les symptômes les plus visibles sont la lenteur de l’application, l’impossibilité de mettre à jour ou corriger un article ou encore ajouter des tags à un nouvel article.
J’avais déjà connu cet état lors d’un crash de la base SQL il y a maintenant quelques années donc je me suis dit que j’allais commencer par redémarrer Apache puis réparer la base de données.
Suppression des instances Apache et redémarrage du service
Dès le lancement de la session SSH, il est évident que quelque chose ne tourne pas rond. Après le message de bienvenue, un message d’erreur apparaît :
/usr/bin/xauth: error in locking authority file /root/.Xauthority
Et en voulant arrêter Apache, on obtient:
Restarting web server: apache2. [error]
There are processes named 'apache2' running which do not match your pid
Code language: JavaScript (javascript)
On commence donc par régler ce problème et on regarde quels sont les PID utilisés par Apache:
pidof apache2
La commande pidof
nous retourne toute une liste de pid:
32691 31385 31154 30917 30663 29150 27368 24820 24563 17531 15227 14235 13559 13064 11028 10906 10256 9156 9144 9042 8855 8542
On met fin à toutes ces instances avec un simple kill -9
:
kill -9 32691 31385 31154 30917 30663 29150 27368 24820 24563 17531 15227 14235 13559 13064 11028 10906 10256 9156 9144 9042 8855 8542
Une fois toutes les instances d’Apache supprimées, il nous est de nouveau possible de redémarrer le service normalement:
service apache2 restart
Ménage dans l’espace disque et le nombre d’inodes disponibles
Au moment de réparer les tables de la base de données, rebelote, erreur :
No space left on device (error 28)
On commence par un petit ménage dans les paquets obsolètes, qui ne résoudra pas grand-chose:
apt-get autoclean && apt-get autoremove
Code language: JavaScript (javascript)
Je tente un simple df
pour vérifier si les disques sont pleins :
df
mais visiblement, non, il reste bien de la place :
Filesystem Size Used Avail Use% Mounted on
/dev/root 9.8G 4.4G 5.0G 47% /
devtmpfs 2.0G 0 2.0G 0% /dev
tmpfs 390M 408K 390M 1% /run
tmpfs 5.0M 0 5.0M 0% /run/lock
tmpfs 780M 0 780M 0% /run/shm
/dev/sda2 683G 531G 118G 82% /home
Code language: PHP (php)
Je tente alors un df -i
pour vérifier le nombres d’inodes disponibles :
df -i
Un nœud d’index ou inode (contraction de l’anglais index et node) est une structure de données contenant des informations à propos d’un fichier stocké dans les systèmes de fichiers Linux/Unix.
À chaque fichier correspond un numéro d’inode (i-number) dans le système de fichiers dans lequel il réside, unique au périphérique sur lequel il est situé.
Les inodes contiennent notamment les métadonnées des systèmes de fichiers, et en particulier celles concernant les droits d’accès.
Les inodes sont créés lors de la création du système de fichiers. La quantité d’inodes (généralement déterminée lors du formatage et dépendant de la taille de la partition) indique le nombre maximum de fichiers que le système de fichiers peut contenir.
Dans notre cas, catastrophe, il ne reste quasiment plus d’inodes disponibles !
Filesystem Inodes IUsed IFree IUse% Mounted on
/dev/root 640K 640K 6 100% /
devtmpfs 487K 1.5K 486K 1% /dev
tmpfs 488K 864 487K 1% /run
tmpfs 488K 10 488K 1% /run/lock
tmpfs 488K 2 488K 1% /run/shm
/dev/sda2 44M 37K 43M 1% /home
Il nous faut donc trouver quels sont les répertoires qui pompent toutes nos inodes. Voici comment identifier les répertoires qui en consomment le plus:
for i in /*; do echo $i; find $i |wc -l; done
for i in /var/*; do echo $i; find $i |wc -l; done
for i in /var/lib/*; do echo $i; find $i |wc -l; done
J’ai répété l’opération jusqu’à me rendre compte que le problème se trouvait dans les milliers de fichiers de session PHP du répertoire /var/lib/php/sessions
.
A ce stade, je ne me suis pas posé de questions – les fichiers de session sont par défaut volatiles, ne durant que le temps d’une session (une visite) et peuvent donc être supprimés sans crainte :
find /var/lib/php/sessions -name '*' | xargs rm
Code language: JavaScript (javascript)
La suppression totale des fichiers a pris plus de dix minutes. Vous pouvez vous assurer de la suppression en calculant la taille du répertoire :
du -s /var/lib/php/sessions
Code language: JavaScript (javascript)
On relance df -i
et là, magie, on a retrouvé un nombre d’inodes disponibles beaucoup plus raisonnable :
Filesystem Inodes IUsed IFree IUse% Mounted on
/dev/root 640K 81K 560K 13% /
devtmpfs 487K 1.5K 486K 1% /dev
tmpfs 488K 864 487K 1% /run
tmpfs 488K 10 488K 1% /run/lock
tmpfs 488K 2 488K 1% /run/shm
/dev/sda2 44M 37K 43M 1% /home
Nous sommes passés de 100% d’utilisation des inodes à 13%, en supprimant plus de 2 Go de données de sessions PHP.
Pour créer un crontab et automatiser la tâche, rendez-vous sur le tutoriel BASH : supprimer les fichiers de session PHP obsolètes.
Réparation de la base de données SQL
Le système étant redevenu stable et réactif, sans avoir à rebooter le serveur, nous pouvons maintenant réparer nos tables SQL au format InnoDB avec :
mysqlrepair -o -A
Puis redémarrer la base de données :
service mysql restart
Attaquons-nous maintenant à la racine du mal : la configuration PHP.
Configuration des sessions sous PHP
Nous allons éditer notre fichier php.ini
pour comprendre pourquoi autant de fichiers de sessions sont créés et surtout pourquoi ils ne sont pas supprimés lorsqu’ils arrivent à expiration.
On commence par trouver le bon fichier php.ini
à éditer en créant une page sur le site avec un simple phpinfo()
.
Il suffit de rechercher la variable Loaded Configuration File :
Loaded Configuration File /etc/php/7.0/fpm/php.ini
On édite php.ini
:
nano /etc/php/7.0/fpm/php.ini
et on vérifie/modifie les valeurs suivantes dans la section [session]
:
session.save_handler = files
session.save_path = ""
session.gc_probability = 1
session.gc_divisor = 100
session.gc_maxlifetime = 1440
session.lazy_write = On
Code language: JavaScript (javascript)
On sauvegarde le fichier et on redémarre Apache et PHP :
service apache2 restart
Notez que j’avais modifié la valeur de la directive session.save_path
il y a quelques mois et lui avait attribué la valeur /var/lib/php/sessions
, ce qui est une erreur monumentale.
En effet, par défaut et depuis quelques versions de PHP, cette valeur est “”, c’est-à-dire que les sessions sont stockées dans le répertoire temporaire du système (/tmp).
Conclusion
Voilà, problème résolu. Tout est revenu à la normale et le nombre de sessions est maintenant revenu à un niveau beaucoup plus correct : le nombre d’inodes utilisé est stabilisé.
Synopsis » Monter un serveur dédié de A à Z
- Serveur dédié : installation d’Apache, PHP, MySQL et Webmin
- Serveur dédié : créer la base de données MySQL et importer WordPress
- Serveur dédié : créer et activer un Virtual Host sous Apache
- Serveur dédié : changer les DNS du nom de domaine et le faire pointer vers le serveur
- Serveur dédié : sécurisation des services avec iptables et fail2ban
- Serveur dédié : sécurisation de la couche TCP/IP
- Serveur dédié : création d’un serveur mail Postfix (sécurisé avec Saslauthd et certificat SSL) et Courier (accès POP et IMAP) utilisant une base MySQL d’utilisateurs/domaines virtuels
- Serveur dédié : sécuriser Apache 2 avec ModSecurity
- Serveur dédié : CHMOD récursif sur des fichiers ou répertoires en ligne de commande
- Serveur dédié : installer APC comme système de cache et configurer Varnish comme reverse-proxy pour Apache pour améliorer les performances
- Serveur dédié : afficher la véritable IP derrière un reverse-proxy comme Varnish
- Serveur dédié : intégrer SSH à WordPress pour mettre à jour le core, les plugins et les thèmes
- Serveur dédié : installer la dernière version d’APC par SVN
- Serveur dédié : analyse des performances du serveur
- Serveur dédié : mettre à jour le noyau Debian de la Kimsufi
- Serveur dédié : sauvegarde automatique des fichiers avec Backup Manager sur le serveur de sauvegarde OVH
- Serveur dédié : configurer la limite mémoire pour PHP et Suhosin
- Bash : supprimer tous les fichiers et sous-répertoires d’un répertoire
- Serveur dédié : impossible de se connecter à un port distant
- Rsync: rapatrier les fichiers du serveur à la maison
- Bash : réparer les tables MySQL en cas de crash
- Serveur dédié : création d’une seedbox avec Transmission
- Serveur dédié : des paquets LAMP à jour sous Debian
- Serveur dédié : mise à jour vers Debian 7 Wheezy
- Serveur dédié : activer X11 forwarding pour SSH
- Serveur dédié : optimiser toutes les images JPG et PNG avec OptiPNG et JpegOptim
- Postfix : résoudre l’erreur “fatal: www-data(33): message file too big”
- Serveur dédié : mise en place de l’IPv6
- WordPress : accorder les bonnes permissions aux fichiers et dossiers avec chown et chmod
- WordPress : héberger les images sur un sous-domaine
- Serveur dédié : ajouter l’authentification SPF, Sender-ID et DKIM à Postfix et Bind9 avec opendkim
- Apache : lorsque le domaine seul (sans WWW) renvoie une erreur 403
- Serveur dédié : sécuriser Apache avec HTTPS (HTTP avec la couche TLS/SSL) en Perfect Forward Secrecy
- Serveur dédié : passer WordPress en HTTPS (TLS/SSL)
- Serveur dédié : configurer Webmin en TLS avec un certificat SSL
- Serveur dédié : configurer Transmission pour accéder au WebUI via TLS-SSL
- Serveur dédié : installer et configurer Varnish 4
- Serveur dédié : passage au mod FastCGI et PHP-FPM avec Apache MPM Worker
- Récupérer un serveur Kimsufi après un plantage de kernel avec le mode rescue OVH
- Serveur dédié : configurer Postfix et Courier pour utiliser TLS-SSL en Perfect Forward Secrecy
- Serveur dédié : retirer Varnish, devenu inutile avec HTTPS
- Serveur dédié : installer la dernière version d’OpenSSL sous Debian
- Serveur dédié : activer l’IP canonique du serveur sous Apache
- Serveur dédié : mise à jour vers PHP 5.6
- MySQL : convertir les tables MyISAM au format InnoDB
- Serveur dédié : optimiser toutes les images GIF avec GIFsicle
- Serveur dédié : migration de MySQL vers MariaDB
- BASH : lister, bloquer et débloquer des adresses IP avec iptables
- Serveur dédié : produire une meilleure réserve d’entropie avec haveged
- Serveur dédié : mettre en place DNSSEC pour sécuriser les DNS du domaine
- Serveur dédié : mise en place du protocole DANE
- 8 règles d’or pour bien déployer DNSSEC et DANE
- Serveur dédié : installer PHP7 FPM avec FastCGI sous Debian
- Serveur dédié : optimiser la couche TCP
- Fail2Ban: protéger Postfix contre les attaques DoS de types AUTH, UNKNOWN et EHLO
- Serveur dédié : mettre à jour Apache pour HTTP/2
- Serveur dédié : ajouter le domaine à la liste HSTS preload
- Serveur dédié : ajouter l’authentification DMARC à Postfix et BIND
- Serveur dédié : à la recherche de l’inode perdue ou comment résoudre le problème “no space left on device”
- Serveur dédié : installer NginX avec support HTTP2 et certificat SSL, PHP, MariaDB sous Debian
Vous avez un projet WordPress ou WooCommerce en tête? Transformez votre vision en réalité avec mon expertise reconnue.