Fix root cause of ControlSocket already exists errors

**Motivations:**
- SSH errors 'ControlSocket already exists, disabling multiplexing' were occurring
- Socket could become invalid between check and execution
- ControlMaster=auto detects invalid socket but doesn't remove it, just disables multiplexing
- Dead socket remains and causes issues for subsequent commands

**Root causes:**
- ControlMaster socket can exist but connection can be dead
- Socket can become invalid between check_ssh_connection() and ssh_exec() execution
- ControlMaster=auto detects invalid socket but doesn't remove it, leaving dead socket
- Dead socket causes 'ControlSocket already exists' errors on subsequent commands
- Previous cleanup was not aggressive enough to remove dead sockets

**Correctifs:**
- Improved check_ssh_connection() to test actual connection with 'true' command instead of just 'ssh -O check'
- Enhanced cleanup_dead_ssh() to remove entire directory instead of just socket file
- This ensures socket is truly removed even if process is still holding it
- Removed complex multi-step cleanup, using simple directory removal and recreation
- Socket validation now tests actual connection usability, not just socket existence

**Evolutions:**
- More robust socket cleanup that guarantees removal of dead sockets
- Better detection of invalid sockets before command execution

**Pages affectées:**
- deploy.sh: Improved cleanup_dead_ssh() and check_ssh_connection() functions
This commit is contained in:
Nicolas Cantu 2026-01-06 14:36:41 +01:00
parent f6cd63a34d
commit 01110cd322

View File

@ -22,20 +22,29 @@ cleanup_dead_ssh() {
# Attendre un peu pour que la fermeture se termine # Attendre un peu pour que la fermeture se termine
sleep 0.5 sleep 0.5
fi fi
# Forcer la suppression du socket même s'il existe encore # Forcer la suppression du socket et du répertoire parent
rm -f "${SSH_CONTROL_PATH}" 2>/dev/null || true # Supprimer le répertoire entier garantit que le socket est vraiment supprimé
# Nettoyer aussi le répertoire parent s'il est vide rm -rf "${SSH_CONTROL_DIR}" 2>/dev/null || true
rmdir "${SSH_CONTROL_DIR}" 2>/dev/null || true # Recréer le répertoire pour les prochaines connexions
mkdir -p "${SSH_CONTROL_DIR}" 2>/dev/null || true
} }
# Fonction pour vérifier si la connexion SSH maître est valide # Fonction pour vérifier si la connexion SSH maître est valide
check_ssh_connection() { check_ssh_connection() {
ssh -O check -o ControlPath="${SSH_CONTROL_PATH}" ${SERVER} 2>/dev/null || return 1 # Vérifier si le socket existe
if [ ! -S "${SSH_CONTROL_PATH}" ]; then
return 1
fi
# Tester la connexion en essayant de l'utiliser avec une commande simple
# Cela détecte si le socket existe mais la connexion est morte
ssh -o ControlPath="${SSH_CONTROL_PATH}" ${SERVER} "true" 2>/dev/null || return 1
return 0
} }
# Fonction pour exécuter une commande SSH avec connexion persistante # Fonction pour exécuter une commande SSH avec connexion persistante
ssh_exec() { ssh_exec() {
# Nettoyer le socket s'il existe mais est invalide # Toujours vérifier et nettoyer le socket avant chaque commande
# pour éviter les sockets morts qui causent "ControlSocket already exists, disabling multiplexing"
if [ -S "${SSH_CONTROL_PATH}" ]; then if [ -S "${SSH_CONTROL_PATH}" ]; then
if ! check_ssh_connection; then if ! check_ssh_connection; then
# Connexion morte, nettoyer avant d'exécuter # Connexion morte, nettoyer avant d'exécuter
@ -44,6 +53,8 @@ ssh_exec() {
fi fi
# Exécuter la commande SSH (une seule tentative, pas de retry) # Exécuter la commande SSH (une seule tentative, pas de retry)
# ControlMaster=auto va créer une nouvelle connexion si le socket n'existe pas,
# ou réutiliser s'il est valide
ssh -o ControlMaster=auto \ ssh -o ControlMaster=auto \
-o ControlPath="${SSH_CONTROL_PATH}" \ -o ControlPath="${SSH_CONTROL_PATH}" \
-o ControlPersist=300 \ -o ControlPersist=300 \