Une connexion SSH n'implique pas d'ouvrir un shell interactif. En passant une commande directement à ssh, vous pouvez interroger, modifier, redémarrer des services ou collecter des informations sur des dizaines de serveurs sans jamais ouvrir un terminal distant.
C'est la base de l'automatisation système et un objectif LFCS (domaine Networking, "Use SSH in automation and scripting").
Dans quel contexte ?
Section intitulée « Dans quel contexte ? »Cette technique s'utilise dès que vous devez agir sur un serveur distant sans ouvrir de session interactive : vérifier l'espace disque après un déploiement, redémarrer un service, collecter des métriques sur plusieurs machines à la fois, ou exécuter un script de provisionnement sans le copier au préalable. C'est aussi le fondement de l'automatisation avec des outils comme Ansible, qui ne fait rien d'autre qu'encapsuler des commandes SSH.
Ce que vous allez apprendre
Section intitulée « Ce que vous allez apprendre »- Lancer une commande sur un serveur sans session interactive
- Combiner
sshavec des pipes pour traiter les données à la volée - Exécuter des commandes qui demandent sudo à distance
- Écrire une boucle multi-serveurs pour des opérations batch
- Passer des scripts locaux à un serveur distant via stdin
- Diagnostiquer les cas où la commande distante échoue silencieusement
Commande simple sur un serveur distant
Section intitulée « Commande simple sur un serveur distant »La syntaxe de base est ssh [options] user@hôte "commande". Dès qu'un argument suit le nom d'hôte, ssh cesse d'ouvrir un shell interactif : il exécute la commande, renvoie sa sortie et referme la connexion. Le shell distant est alors lancé en mode non interactif, ce qui a une conséquence pratique importante : ni ~/.bashrc ni le prompt ne sont chargés, et le PATH peut différer de celui d'une session ordinaire.
# Lire les 5 dernières lignes des logs d'authentificationssh bob@192.168.1.10 "tail -5 /var/log/auth.log"
# Vérifier l'espace disquessh bob@192.168.1.10 "df -h /"
# Voir les processus qui tournentssh bob@192.168.1.10 "ps aux | grep nginx"Le résultat s'affiche directement dans votre terminal local. Pas de session, pas de prompt distant.
Pipes entre machine locale et serveur distant
Section intitulée « Pipes entre machine locale et serveur distant »ssh lit son entrée standard et écrit sur sa sortie standard comme n'importe quelle commande : il s'insère donc au milieu d'un pipeline shell ordinaire. Toute la difficulté tient à savoir de quel côté chaque morceau du pipeline s'exécute. Ce qui est à l'intérieur des guillemets tourne sur le serveur, ce qui est à l'extérieur tourne sur votre machine.
Lire un fichier distant et filtrer localement
Section intitulée « Lire un fichier distant et filtrer localement »Le grep est ici placé après le pipe, donc hors des guillemets : il travaille sur votre machine, sur le flux renvoyé par le serveur.
# Récupérer /etc/hosts distant et filtrer les lignes webssh bob@192.168.1.10 "cat /etc/hosts" | grep webEnvoyer des données locales vers le serveur
Section intitulée « Envoyer des données locales vers le serveur »Le sens inverse fonctionne aussi : le - de tar czf - écrit l'archive sur la sortie standard, que ssh transmet à l'entrée standard du tar distant. Rien ne touche le disque intermédiaire, ce qui évite d'avoir à prévoir de l'espace pour un fichier temporaire.
# Compresser localement et décompresser à distance (alternative à rsync)tar czf - /data/backups | ssh bob@192.168.1.10 "tar xzf - -C /restore/"Lire plusieurs fichiers distants avec des wildcards
Section intitulée « Lire plusieurs fichiers distants avec des wildcards »Un motif comme *.log doit rester protégé par les guillemets : sinon votre shell local tente de le résoudre contre vos propres fichiers, et transmet au serveur soit un chemin faux, soit le motif brut selon les fichiers présents dans le répertoire courant.
# Les wildcards doivent être entre guillemets pour être évalués à distancessh bob@192.168.1.10 "cat /var/log/nginx/*.log" | grep "500"Commandes nécessitant sudo
Section intitulée « Commandes nécessitant sudo »L'élévation de privilèges est le premier obstacle rencontré en exécution distante, parce qu'une commande passée à ssh ne dispose par défaut d'aucun terminal. Or beaucoup de configurations sudo refusent de lire un mot de passe autrement que sur un terminal, via l'option requiretty ou simplement parce qu'aucun autre canal de saisie n'existe. Deux réponses existent : allouer un pseudo-terminal, ou se passer complètement de mot de passe.
Pseudo-TTY avec -t
Section intitulée « Pseudo-TTY avec -t »sudo sur certains systèmes exige un terminal (TTY). L'option -t alloue un pseudo-TTY :
ssh -t bob@192.168.1.10 "sudo systemctl restart nginx"Sans -t, vous obtenez : sudo: a terminal is required to read the password
Lancer une commande root avec entrée standard
Section intitulée « Lancer une commande root avec entrée standard »Le script local est envoyé à un bash privilégié qui le lit sur son entrée standard, sans jamais être écrit sur le disque distant.
# Passer un script à exécuter avec sudocat script_local.sh | ssh -t bob@192.168.1.10 "sudo bash"Passer un script local à distance
Section intitulée « Passer un script local à distance »Plutôt que de copier un script sur le serveur, passez-le directement via stdin. L'option -s de bash lui demande de lire le script sur son entrée standard au lieu d'attendre un nom de fichier, ce qui permet de conserver les arguments passés en ligne de commande. Aucun fichier n'est déposé sur la machine cible, donc aucun nettoyage à prévoir et aucune trace laissée dans /tmp.
# Exécuter un script local sur le serveur distantssh bob@192.168.1.10 "bash -s" < mon_script.shAvec des arguments :
ssh bob@192.168.1.10 "bash -s" < mon_script.sh -- --env production --dry-runOpérations batch sur plusieurs serveurs
Section intitulée « Opérations batch sur plusieurs serveurs »Une boucle shell autour de ssh suffit pour appliquer la même commande à un parc entier, sans installer le moindre outil supplémentaire. Le fonctionnement est séquentiel : chaque hôte attend que le précédent ait terminé, et un serveur injoignable fait patienter toute la boucle jusqu'à l'expiration du délai de connexion. C'est acceptable sur quelques machines, beaucoup moins au-delà.
Boucle simple
Section intitulée « Boucle simple »La liste des hôtes est écrite en dur dans la boucle, et l'echo sert de séparateur visuel : sans lui, les sorties des différents serveurs se confondent.
for host in web1 web2 web3 db1; do echo "=== $host ===" ssh bob@$host "uptime && df -h /"doneBoucle depuis un fichier de liste
Section intitulée « Boucle depuis un fichier de liste »Sortir la liste dans un fichier évite de modifier le script à chaque changement de parc. Attention toutefois : ssh consomme l'entrée standard de la boucle, ce qui interrompt la lecture du fichier dès le premier hôte. L'option -n de ssh, ou une redirection vers un autre descripteur, est nécessaire dès que la commande distante lit stdin.
# servers.txt contient un hôte par lignewhile read host; do echo "=== $host ===" ssh bob@$host "free -h | grep Mem"done < servers.txtCollecte système multi-serveurs (format tabulé)
Section intitulée « Collecte système multi-serveurs (format tabulé) »Produire du CSV rend la sortie exploitable par un tableur ou un script d'analyse. Les \$ échappés sont indispensables : ils empêchent votre shell local de résoudre les variables awk avant l'envoi, alors qu'elles n'ont de sens que sur le serveur distant.
echo "HOST,UPTIME,MEMORY_FREE,DISK_FREE"for host in web1 web2 web3; do ssh bob@$host "echo -n '${host},'; uptime | awk '{print \$(NF-2)}' | tr -d ','; echo -n ','; free -m | awk '/Mem/{print \$4}'; df -h / | awk 'NR==2{print \$4}'"doneCodes de retour et gestion d'erreur
Section intitulée « Codes de retour et gestion d'erreur »ssh transmet le code de retour de la commande distante, exploitable directement dans un test shell. Une nuance compte pour écrire des scripts fiables : ssh réserve le code 255 à ses propres erreurs (hôte injoignable, authentification refusée, clé rejetée). Un code 255 ne dit donc rien de la commande demandée, il signale que la connexion elle-même a échoué.
if ssh bob@192.168.1.10 "systemctl is-active nginx" > /dev/null 2>&1; then echo "nginx actif sur 192.168.1.10"else echo "ALERTE : nginx inactif sur 192.168.1.10"fiQuitter immédiatement si une commande échoue dans une boucle :
set -efor host in web1 web2 web3; do ssh bob@$host "test -f /var/lock/deploy.lock && exit 1 || true"doneTunneling + commande distante
Section intitulée « Tunneling + commande distante »Une commande distante s'exécute aussi sur une machine que vous ne joignez pas directement. L'option -J (ProxyJump) fait rebondir la connexion par un bastion : le trafic transite chiffré de bout en bout, et le bastion ne voit passer qu'un flux qu'il ne peut pas déchiffrer. Votre clé privée reste sur votre poste, elle n'est jamais copiée sur la machine intermédiaire.
# Via ProxyJump en one-liner : commande sur un serveur de prod accessible via bastionssh -J bob@bastion.example.com bob@10.0.1.15 "systemctl status app"Dépannage
Section intitulée « Dépannage »Presque tous les échecs d'exécution distante viennent du même malentendu : la commande n'a pas été interprétée là où vous le pensiez, ou l'environnement du shell non interactif diffère de celui de votre session habituelle. Avant de chercher plus loin, vérifiez que la commande est bien entourée de guillemets et testez-la dans une session SSH ouverte à la main.
| Symptôme | Cause probable | Action |
|---|---|---|
sudo: a terminal is required | sudo exige un TTY | Ajouter -t à la commande ssh |
| La commande s'exécute localement | Guillemets oubliés autour de la commande | Entourer la commande de "..." |
bash: commande: not found, hors session | Variables PATH différentes en mode non-interactif | Utiliser le chemin absolu ou bash -l -c "..." |
| Code de retour 255 inattendu | 255 est le code d'erreur propre à ssh : la connexion a échoué avant l'exécution | Vérifier l'accès réseau, la clé et le nom d'hôte ; un vrai 255 distant est indiscernable |
| Commande bloquée sans fin | Programme distant attend une entrée | Ajouter -n pour désactiver stdin : ssh -n ... |
Contrôle de connaissances
Section intitulée « Contrôle de connaissances »Vérifiez que l'essentiel de ce guide est acquis. Les questions portent uniquement sur ce qui vient d'être expliqué ici.
Contrôle de connaissances
Validez vos connaissances avec ce quiz interactif
Informations
- Le chronomètre démarre au clic sur Démarrer
- Questions à choix multiples, vrai/faux et réponses courtes
- Vous pouvez naviguer entre les questions
- Les résultats détaillés sont affichés à la fin
Lance le quiz et démarre le chronomètre
Vérification
(0/0)Profil de compétences
Quoi faire maintenant
Ressources pour progresser
Des indices pour retenter votre chance ?
Nouveau quiz complet avec des questions aléatoires
Retravailler uniquement les questions ratées
Retour à la liste des certifications
À retenir
Section intitulée « À retenir »ssh user@host "commande"exécute sans ouvrir de session, la commande doit être entre guillemets-talloue un pseudo-TTY nécessaire poursudointeractifbash -s < script.shexécute un script local à distance sans le copier- Le code de retour de la commande distante est transmis par SSH, utilisez-le dans vos scripts
- Pour du batch à grande échelle, ControlMaster ou Ansible sont plus adaptés que les boucles
for
Pour aller plus loin
Section intitulée « Pour aller plus loin »- Transférer des fichiers avec rsync : Synchronisation efficace quand le pipe SSH ne suffit plus.