Service backend down
Quand le serveur web fonctionne mais pas le reste
PHP-FPM crashé, MySQL saturé, Redis indisponible : rétablissez vos services.
Les symptômes révélateurs
Vous êtes face à un problème de backend si :
- Les fichiers statiques chargent (images, CSS, JS) mais pas les pages PHP
- Nginx/Apache répond mais avec une erreur 502 Bad Gateway ou 503
- Les logs Nginx montrent des erreurs « upstream » ou « connect() failed »
- La commande
systemctl status php-fpmmontre « inactive » ou « failed » - Le site fonctionnait et s’est arrêté brutalement (pas progressivement)
La différence avec une surcharge : ici, un service est complètement arrêté, pas simplement submergé. Le redémarrage résout souvent le problème immédiat.
Diagnostic rapide : État des services
Commande unique pour tout vérifier
$ systemctl status nginx php8.2-fpm mysql redis-server --no-pager
● nginx.service - A high performance web server
Active: active (running) ✅
● php8.2-fpm.service - The PHP 8.2 FastCGI Process Manager
Active: inactive (dead) ❌ ← PROBLÈME
● mysql.service - MySQL Community Server
Active: active (running) ✅
● redis-server.service - Advanced key-value store
Active: active (running) ✅
Vérifier chaque service individuellement
# PHP-FPM
$ systemctl status php8.2-fpm
$ ps aux | grep php-fpm
# MySQL / MariaDB
$ systemctl status mysql
$ mysqladmin -u root -p ping
# Réponse attendue : "mysqld is alive"
# Redis
$ systemctl status redis-server
$ redis-cli ping
# Réponse attendue : "PONG"
# Memcached
$ systemctl status memcached
$ echo "stats" | nc localhost 11211 | head
Problème 1 : PHP-FPM down
C’est la cause la plus fréquente de 502/503 quand Nginx fonctionne.
Diagnostic
# État du service
$ systemctl status php8.2-fpm
● php8.2-fpm.service - The PHP 8.2 FastCGI Process Manager
Active: failed (Result: exit-code) ❌
Process: 1234 ExecStart=... (code=exited, status=78)
# Logs détaillés
$ journalctl -u php8.2-fpm -n 50 --no-pager
# Logs PHP-FPM
$ tail -50 /var/log/php8.2-fpm.log
Erreurs courantes et solutions
Erreur : « unable to bind listening socket »
$ journalctl -u php8.2-fpm | grep "bind"
unable to bind listening socket for address '/run/php/php8.2-fpm.sock'
Cause : Le socket existe déjà (crash précédent) ou permissions incorrectes.
Solution :
$ rm -f /run/php/php8.2-fpm.sock
$ systemctl start php8.2-fpm
Erreur : « pm.max_children reached »
$ grep "max_children" /var/log/php8.2-fpm.log
WARNING: [pool www] server reached pm.max_children setting (5)
Cause : Tous les workers PHP sont occupés, les nouvelles requêtes sont refusées.
Solution : Augmenter pm.max_children dans la config du pool :
/etc/php/8.2/fpm/pool.d/www.conf
pm = dynamic
pm.max_children = 50 ; Augmenter selon RAM disponible
pm.start_servers = 10
pm.min_spare_servers = 5
pm.max_spare_servers = 20
Erreur : « OOM killer » (Out Of Memory)
$ dmesg | grep -i "killed process"
[12345.678] Out of memory: Killed process 9876 (php-fpm)
Cause : Le serveur manque de RAM, le kernel tue PHP-FPM pour survivre.
Solution :
- Réduire
pm.max_children - Ajouter de la RAM
- Optimiser la consommation mémoire des scripts
Redémarrage et vérification
# Redémarrer PHP-FPM
$ systemctl restart php8.2-fpm
# Vérifier qu'il tourne
$ systemctl status php8.2-fpm
● php8.2-fpm.service
Active: active (running) ✅
# Vérifier que le socket existe
$ ls -la /run/php/php8.2-fpm.sock
srw-rw---- 1 www-data www-data 0 Dec 26 14:30 /run/php/php8.2-fpm.sock
# Tester une page PHP
$ curl -I https://monsite.com
HTTP/1.1 200 OK ✅
Problème 2 : MySQL / MariaDB down ou saturé
Diagnostic
# État du service
$ systemctl status mysql
# Tester la connexion
$ mysql -u root -p -e "SELECT 1"
ERROR 2002 (HY000): Can't connect to local MySQL server through socket '/var/run/mysqld/mysqld.sock'
# ❌ MySQL est down
# Ou
$ mysql -u root -p -e "SELECT 1"
ERROR 1040 (HY000): Too many connections
# ❌ MySQL saturé
MySQL down : Causes et solutions
Vérifier les logs :
$ tail -100 /var/log/mysql/error.log
Erreurs fréquentes :
| Erreur | Cause | Solution |
|---|---|---|
| « InnoDB: Unable to lock ./ibdata1 » | Crash précédent, fichier verrouillé | rm /var/lib/mysql/ib_logfile* puis restart |
| « disk full » | Plus d’espace disque | Libérer de l’espace, purger les logs |
| « Out of memory » | RAM insuffisante | Réduire innodb_buffer_pool_size |
| « Too many open files » | Limite système | Augmenter ulimit |
Redémarrer MySQL :
$ systemctl restart mysql
# Si ça ne démarre pas, mode recovery
$ mysqld_safe --skip-grant-tables &
# Puis investiguer et réparer
MySQL saturé : « Too many connections »
# Voir les connexions actives
$ mysql -u root -p -e "SHOW PROCESSLIST;"
+----+------+-----------+------+---------+------+-------+------------------+
| Id | User | Host | db | Command | Time | State | Info |
+----+------+-----------+------+---------+------+-------+------------------+
| 1 | root | localhost | NULL | Query | 0 | init | SHOW PROCESSLIST |
| 2 | web | localhost | shop | Sleep | 300 | NULL | NULL |
| 3 | web | localhost | shop | Sleep | 298 | NULL | NULL |
# ... des dizaines de connexions "Sleep"
Solution immédiate : Killer les connexions dormantes
$ mysql -u root -p -e "
SELECT CONCAT('KILL ', id, ';')
FROM information_schema.processlist
WHERE command = 'Sleep' AND time > 300;" | mysql -u root -p
Solution durable : Ajuster la configuration
/etc/mysql/mysql.conf.d/mysqld.cnf
[mysqld]
# Augmenter si nécessaire (attention à la RAM)
max_connections = 200
# Fermer les connexions inactives plus vite
wait_timeout = 60
interactive_timeout = 60
# Optimiser InnoDB
innodb_buffer_pool_size = 1G # 50-70% de la RAM disponible
Problème 3 : Problème de socket / communication
Nginx et PHP-FPM communiquent via un socket Unix ou un port TCP. Si la configuration ne correspond pas, 502/503.
Vérifier la configuration Nginx
$ grep -r "fastcgi_pass" /etc/nginx/
/etc/nginx/sites-available/monsite.conf: fastcgi_pass unix:/run/php/php8.2-fpm.sock;
Vérifier la configuration PHP-FPM
$ grep "listen" /etc/php/8.2/fpm/pool.d/www.conf
listen = /run/php/php8.2-fpm.sock
Les deux doivent correspondre !
Vérifier que le socket existe et est accessible
$ ls -la /run/php/php8.2-fpm.sock
srw-rw---- 1 www-data www-data 0 Dec 26 14:30 /run/php/php8.2-fpm.sock
# L'utilisateur Nginx doit pouvoir y accéder
$ ps aux | grep nginx
www-data 1234 ... nginx: worker process
# ✅ Nginx tourne en www-data, qui est propriétaire du socket
Configuration correcte
/etc/php/8.2/fpm/pool.d/www.conf
[www]
user = www-data
group = www-data
listen = /run/php/php8.2-fpm.sock
listen.owner = www-data
listen.group = www-data
listen.mode = 0660
/etc/nginx/sites-available/monsite.conf
location ~ \\.php$ {
fastcgi_pass unix:/run/php/php8.2-fpm.sock;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
include fastcgi_params;
# Timeouts (évite les 504)
fastcgi_read_timeout 300;
fastcgi_send_timeout 300;
}
Problème 4 : Redis / Memcached down
Si votre application utilise Redis ou Memcached pour le cache ou les sessions, leur indisponibilité peut causer des erreurs.
Redis
# État du service
$ systemctl status redis-server
# Test de connexion
$ redis-cli ping
PONG # ✅ OK
# Si erreur de connexion
$ redis-cli ping
Could not connect to Redis at 127.0.0.1:6379: Connection refused
# ❌ Redis down
# Redémarrer
$ systemctl restart redis-server
# Vérifier les logs
$ tail -50 /var/log/redis/redis-server.log
Erreur fréquente : « maxmemory reached »
$ redis-cli info memory | grep used_memory_human
used_memory_human:256.00M
# Si Redis est plein, il refuse les écritures
$ redis-cli set test "value"
(error) OOM command not allowed when used memory > 'maxmemory'
Solution :
/etc/redis/redis.conf
# Augmenter la limite
maxmemory 512mb
# Politique d'éviction (supprimer les clés les moins utilisées)
maxmemory-policy allkeys-lru
Memcached
# État du service
$ systemctl status memcached
# Test
$ echo "stats" | nc localhost 11211 | head
STAT pid 12345
STAT uptime 123456
# ✅ OK
# Redémarrer si down
$ systemctl restart memcached
Impact sur les sessions : Si vos sessions PHP sont stockées dans Redis/Memcached et que le service est down, tous vos utilisateurs seront déconnectés. Prévoyez un fallback vers les fichiers en cas de problème.
Script de diagnostic complet
/usr/local/bin/check-backend.sh
#!/bin/bash
# Script de diagnostic des services backend
echo "=== DIAGNOSTIC BACKEND ==="
echo ""
# Fonction de check
check_service() {
local service=$1
local name=$2
if systemctl is-active --quiet $service; then
echo "✅ $name : OK"
else
echo "❌ $name : DOWN"
echo " → systemctl start $service"
fi
}
# Vérifier les services
check_service nginx "Nginx"
check_service php8.2-fpm "PHP-FPM"
check_service mysql "MySQL"
check_service redis-server "Redis"
echo ""
echo "=== RESSOURCES ==="
# RAM
free -h | awk 'NR==2{printf "RAM: %s / %s (%.1f%% utilisé)\
", $3, $2, $3/$2*100}'
# Disque
df -h / | awk 'NR==2{printf "Disque: %s / %s (%s utilisé)\
", $3, $2, $5}'
# Load
echo "Load: $(uptime | awk -F'load average:' '{print $2}')"
echo ""
echo "=== CONNEXIONS ==="
# Connexions MySQL
mysql -u root -pPASSWORD -e "SELECT COUNT(*) as 'MySQL connexions' FROM information_schema.processlist;" 2>/dev/null || echo "MySQL: impossible de se connecter"
# Workers PHP
echo "PHP-FPM workers: $(ps aux | grep 'php-fpm: pool' | wc -l)"
echo ""
echo "=== ERREURS RECENTES ==="
echo "-- PHP-FPM --"
tail -5 /var/log/php8.2-fpm.log 2>/dev/null | grep -i error || echo "Aucune erreur récente"
echo "-- MySQL --"
tail -5 /var/log/mysql/error.log 2>/dev/null | grep -i error || echo "Aucune erreur récente"
echo ""
echo "=== FIN DIAGNOSTIC ==="
$ chmod +x /usr/local/bin/check-backend.sh
$ check-backend.sh
Automatiser le redémarrage des services
Avec systemd (service auto-restart)
/etc/systemd/system/php8.2-fpm.service.d/restart.conf
[Service]
Restart=on-failure
RestartSec=5s
$ systemctl daemon-reload
$ systemctl restart php8.2-fpm
Avec un script cron de surveillance
/usr/local/bin/watch-backend.sh
#!/bin/bash
# Redémarre automatiquement les services down
restart_if_dead() {
local service=$1
if ! systemctl is-active --quiet $service; then
echo "$(date): $service down, redémarrage..." >> /var/log/backend-watch.log
systemctl restart $service
fi
}
restart_if_dead php8.2-fpm
restart_if_dead mysql
restart_if_dead redis-server
# Cron toutes les minutes
$ crontab -e
* * * * * /usr/local/bin/watch-backend.sh
Cette surveillance automatique est un pansement, pas une solution. Si un service crash régulièrement, il faut trouver et corriger la cause racine.
Infrastructure fiable et résiliente
Monitoring proactif, haute disponibilité, intervention 24/7.
Questions fréquentes
Pourquoi PHP-FPM crash-t-il régulièrement ?
Les causes les plus fréquentes sont : mémoire insuffisante (OOM), erreurs fatales PHP répétées (bug applicatif), configuration pm.max_children inadaptée, ou fuite mémoire dans un script. Analysez les logs et le dmesg pour identifier la cause exacte.
Comment savoir si c’est MySQL ou PHP le problème ?
Testez MySQL directement : mysql -u root -p -e "SELECT 1". Si ça fonctionne, MySQL est OK et le problème vient de PHP ou de la connexion PHP→MySQL. Vérifiez aussi les logs PHP pour des erreurs de connexion PDO.
Puis-je utiliser plusieurs versions de PHP-FPM ?
Oui, c’est courant. Installez plusieurs versions (php7.4-fpm, php8.2-fpm), configurez chacune avec son propre socket, et pointez chaque site vers le bon socket dans Nginx. Utile pour les migrations progressives.
Le site marche en HTTP mais pas en HTTPS, pourquoi ?
Ce n’est généralement pas un problème de backend mais de certificat SSL ou de configuration Nginx. Vérifiez que le bloc server pour le port 443 a bien la même configuration PHP que celui du port 80.