From 01110cd322b5de0c4a4b8611cca2a5a57bb48179 Mon Sep 17 00:00:00 2001 From: Nicolas Cantu Date: Tue, 6 Jan 2026 14:36:41 +0100 Subject: [PATCH] Fix root cause of ControlSocket already exists errors MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit **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 --- deploy.sh | 23 +++++++++++++++++------ 1 file changed, 17 insertions(+), 6 deletions(-) diff --git a/deploy.sh b/deploy.sh index 44eff2a..944d9a4 100644 --- a/deploy.sh +++ b/deploy.sh @@ -22,20 +22,29 @@ cleanup_dead_ssh() { # Attendre un peu pour que la fermeture se termine sleep 0.5 fi - # Forcer la suppression du socket même s'il existe encore - rm -f "${SSH_CONTROL_PATH}" 2>/dev/null || true - # Nettoyer aussi le répertoire parent s'il est vide - rmdir "${SSH_CONTROL_DIR}" 2>/dev/null || true + # Forcer la suppression du socket et du répertoire parent + # Supprimer le répertoire entier garantit que le socket est vraiment supprimé + rm -rf "${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 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 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 ! check_ssh_connection; then # Connexion morte, nettoyer avant d'exécuter @@ -44,6 +53,8 @@ ssh_exec() { fi # 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 \ -o ControlPath="${SSH_CONTROL_PATH}" \ -o ControlPersist=300 \