<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
  <channel>
    <title>Bash on Bastien Traverse</title>
    <link>https://bastientraverse.com/fr/tags/bash/</link>
    <description>Recent content in Bash on Bastien Traverse</description>
    <generator>Hugo -- gohugo.io</generator>
    <language>fr</language>
    <lastBuildDate>Sat, 14 Mar 2026 00:00:00 +0100</lastBuildDate><atom:link href="https://bastientraverse.com/fr/tags/bash/index.xml" rel="self" type="application/rss+xml" />
    <item>
      <title>Exécuter la même tâche sur plusieurs machines avec Bash et sshpass</title>
      <link>https://bastientraverse.com/fr/articles/2026-03/automatisation/</link>
      <pubDate>Sat, 14 Mar 2026 00:00:00 +0100</pubDate>
      
      <guid>https://bastientraverse.com/fr/articles/2026-03/automatisation/</guid>
      <description>&lt;p&gt;Dans le cadre du défi &amp;ldquo;&lt;a href=&#34;https://kodekloud.com/100-days-of-devops&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;100 jours de DevOps&lt;/a&gt;&amp;rdquo; de la plateforme KodeKloud, une des tâches fournies consistait à installer &lt;em&gt;cronie&lt;/em&gt; sur trois serveurs et à créer la même tâche cron pour l&amp;rsquo;utilisateur root :&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;The Nautilus system admins team has prepared scripts to automate several day-to-day tasks. They want them to be deployed on all app servers in Stratos DC on a set schedule. Before that they need to test similar functionality with a sample cron job. Therefore, perform the steps below:&lt;br&gt;
a. Install &lt;code&gt;cronie&lt;/code&gt; package on all Nautilus app servers and start &lt;code&gt;crond&lt;/code&gt; service.&lt;br&gt;
b. Add a cron &lt;code&gt;*/5 * * * * echo hello &amp;gt; /tmp/cron_text&lt;/code&gt; for root user.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;À la lecture de l&amp;rsquo;énoncé j&amp;rsquo;entrevoyais déjà la procédure attendue, manuelle et répétitive :&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;récupérer les identifiants du premier serveur et s&amp;rsquo;y connecter en SSH&lt;/li&gt;
&lt;li&gt;installer le paquet &lt;em&gt;cronie&lt;/em&gt;&lt;/li&gt;
&lt;li&gt;vérifier l&amp;rsquo;état du service&lt;/li&gt;
&lt;li&gt;éditer le crontab root&lt;/li&gt;
&lt;li&gt;déconnexion et répétition avec les deux serveurs suivants.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;J&amp;rsquo;ai une horreur viscérale de ce genre de répétitions robotiques sans intérêt ; ça fait crier quelque chose au fond de moi : &amp;ldquo;Je ne suis pas une machine !&amp;rdquo; Car c&amp;rsquo;est à la machine que revient d&amp;rsquo;effectuer ce genre de tâches : le mot informatique n&amp;rsquo;est-il pas la contraction de &lt;em&gt;information automatique&lt;/em&gt; après tout ?&lt;/p&gt;
&lt;p&gt;Ce qui m&amp;rsquo;intéresse dans l&amp;rsquo;approche DevOps c&amp;rsquo;est exactement ça : mettre un terme à cette manière manuelle et fastidieuse de procéder, et parachever enfin la raison d&amp;rsquo;être de l&amp;rsquo;informatique. On veut de l&amp;rsquo;industrialisation, de l&amp;rsquo;automatisation, de l&amp;rsquo;&lt;em&gt;Infra-as-Code&lt;/em&gt; enfin !&lt;/p&gt;
&lt;hr&gt;
&lt;p&gt;J&amp;rsquo;ai donc commencé par envisager mes alternatives :&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;installer Ansible et créer un playbook : overkill pour un lab unique, entre l&amp;rsquo;installation et l&amp;rsquo;écriture ça aurait introduit une complexité inutile à ce stade ; je suis sûr que je dois pouvoir faire cela avec les outils à ma disposition.&lt;/li&gt;
&lt;li&gt;mon petit chouchou, &lt;a href=&#34;https://www.gnu.org/software/parallel/&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;GNU parallel&lt;/a&gt; : pas installé dans l&amp;rsquo;environnement du lab, suppose une connexion par clé SSH pour se passer de mot de passe.&lt;/li&gt;
&lt;li&gt;reste le script Bash traditionnel.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;J&amp;rsquo;ai commencé par établir la procédure opératoire précise pour la traduire en commandes impératives :&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;pour se connecter à chaque serveur : &lt;code&gt;ssh user1@server1&lt;/code&gt;, acceptation de la clé d&amp;rsquo;hôte puis entrée du mot de passe de l&amp;rsquo;utilisateur&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;exécution des trois commandes pour répondre à l&amp;rsquo;énoncé :&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-shell&#34; data-lang=&#34;shell&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;sudo dnf install -y cronie
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;sudo systemctl start crond &lt;span class=&#34;c1&#34;&gt;# pas nécessaire car le service est démarré automatiquement&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nb&#34;&gt;echo&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;*/5 * * * * echo hello &amp;gt; /tmp/cron_text&amp;#34;&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;|&lt;/span&gt; sudo tee -a /etc/crontab
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Pour automatiser cela :&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Je peux utiliser l&amp;rsquo;options &lt;code&gt;-o StrictHostKeyChecking=no&lt;/code&gt; pour contourner l&amp;rsquo;acceptation de la clé d&amp;rsquo;hôte&lt;/li&gt;
&lt;li&gt;Je peux recourir à &lt;a href=&#34;https://sourceforge.net/projects/sshpass/&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;sshpass&lt;/a&gt; pour fournir le mot de passe de manière non-interactive (par miracle il est installé sur la machine du lab)&lt;/li&gt;
&lt;li&gt;Une petite recherche m&amp;rsquo;apprend que &lt;code&gt;sudo&lt;/code&gt; accepte l&amp;rsquo;option &lt;code&gt;-S, --stdin&lt;/code&gt; pour &amp;ldquo;lire le mot de passe depuis l&amp;rsquo;entrée standard&amp;rdquo;.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Tout ceci mis ensemble donne pour le premier serveur :&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-shell&#34; data-lang=&#34;shell&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;sshpass -p Ir0nM@n ssh -o &lt;span class=&#34;nv&#34;&gt;StrictHostKeyChecking&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;no tony@stapp01 &lt;span class=&#34;se&#34;&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;se&#34;&gt;&lt;/span&gt;    &lt;span class=&#34;s1&#34;&gt;&amp;#39;sudo -S dnf install -y cronie &amp;lt;&amp;lt;&amp;lt; &amp;#34;Ir0nM@n&amp;#34; &amp;amp;&amp;amp;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;s1&#34;&gt;     echo &amp;#34;*/5 * * * * echo hello &amp;gt; /tmp/cron_text&amp;#34; | sudo tee -a /etc/crontab&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Ou sur une seule ligne :&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-shell&#34; data-lang=&#34;shell&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;sshpass -p Ir0nM@n ssh -o &lt;span class=&#34;nv&#34;&gt;StrictHostKeyChecking&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;no tony@stapp01 &lt;span class=&#34;s1&#34;&gt;&amp;#39;sudo -S dnf install -y cronie &amp;lt;&amp;lt;&amp;lt; &amp;#34;Ir0nM@n&amp;#34; &amp;amp;&amp;amp; echo &amp;#34;*/5 * * * * echo hello &amp;gt; /tmp/cron_text&amp;#34; | sudo tee -a /etc/crontab&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Ok, c&amp;rsquo;est un peu hacky mais à ma bonne surprise ça fonctionne !&lt;/p&gt;
&lt;p&gt;La deuxième étape a été d&amp;rsquo;extraire les parties communes dans des variables :&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nv&#34;&gt;SSH_OPTIONS&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s1&#34;&gt;&amp;#39;-o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null -o LogLevel=ERROR&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nv&#34;&gt;COMMAND&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s1&#34;&gt;&amp;#39;sudo -S dnf install -y cronie &amp;lt;&amp;lt;&amp;lt; $PASSWORD &amp;amp;&amp;amp; echo &amp;#34;*/5 * * * * echo hello &amp;gt; /tmp/cron_text&amp;#34; | sudo tee -a /etc/crontab&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;sshpass -p Ir0nM@n ssh &lt;span class=&#34;nv&#34;&gt;$SSH_OPTIONS&lt;/span&gt; tony@stapp01 &lt;span class=&#34;nv&#34;&gt;$COMMAND&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;sshpass -p Am3ric@ ssh &lt;span class=&#34;nv&#34;&gt;$SSH_OPTIONS&lt;/span&gt; steve@stapp02 &lt;span class=&#34;nv&#34;&gt;$COMMAND&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;sshpass -p BigGr33n ssh &lt;span class=&#34;nv&#34;&gt;$SSH_OPTIONS&lt;/span&gt; banner@stapp03 &lt;span class=&#34;nv&#34;&gt;$COMMAND&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Restait à intégrer le mot de passe comme variable, utilisée à la fois pour se connecter en SSH et pour le premier &lt;code&gt;sudo&lt;/code&gt; une fois connecté. Le petit défi est :&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;de faire se correspondre le binôme &lt;code&gt;utilisateur@machine&lt;/code&gt; avec le bon mot de passe, et de les changer à chaque itération&lt;/li&gt;
&lt;li&gt;de passer le mot de passe à l&amp;rsquo;intérieur de la variable contenant la commande&amp;hellip;&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;À ce stade je voyais bien qu&amp;rsquo;il ne me manquait plus qu&amp;rsquo;un petit effort pour parvenir à automatiser cette procédure et qu&amp;rsquo;elle fonctionne sur les trois serveurs.&lt;/p&gt;
&lt;p&gt;Mon intuition d&amp;rsquo;une boucle &lt;code&gt;for&lt;/code&gt; ne convient pas : même en en imbriquant plusieurs les différents paramètres associés ne se conjugueraient pas correctement.&lt;/p&gt;
&lt;p&gt;Attendez un instant, &amp;ldquo;paramètres associés&amp;rdquo;&amp;hellip;Associatif&amp;hellip; Comme un &lt;em&gt;tableau associatif&lt;/em&gt; ?&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;https://media4.giphy.com/media/v1.Y2lkPTc5MGI3NjExazRqZ3RuNWRiZjU2MTU4azc4YzcwaTF0YzdoZjdlYjc1aGRpanB4MCZlcD12MV9pbnRlcm5hbF9naWZfYnlfaWQmY3Q9Zw/26ufdipQqU2lhNA4g/giphy.gif&#34;&gt;&lt;/p&gt;
&lt;p&gt;Voilà, c&amp;rsquo;est ça qu&amp;rsquo;il me faut : établir un &lt;a href=&#34;https://web.archive.org/web/20240419190410/http://aral.iut-rodez.fr/fr/sanchis/enseignement/bash/ch12s02-Tableaux-associatifs.html&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;tableau associatif&lt;/a&gt; &amp;lsquo;utilisateur-serveur-mot de passe&amp;rsquo; et itérer dessus pour exécuter les commandes !&lt;/p&gt;
&lt;p&gt;N&amp;rsquo;utilisant pas souvent cette forme de variable dans Bash, c&amp;rsquo;était le moment pour moi de recourir à un LLM pour accélérer la conception du script. Je vous laisse admirer le résultat :&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nv&#34;&gt;SSH_OPTIONS&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s1&#34;&gt;&amp;#39;-o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null -o LogLevel=ERROR&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nb&#34;&gt;declare&lt;/span&gt; -A &lt;span class=&#34;nv&#34;&gt;HOSTS&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=(&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  &lt;span class=&#34;o&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;tony@stapp01&amp;#34;&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;]=&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;Ir0nM@n&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  &lt;span class=&#34;o&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;steve@stapp02&amp;#34;&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;]=&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;Am3ric@&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  &lt;span class=&#34;o&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;banner@stapp03&amp;#34;&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;]=&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;BigGr33n&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;o&#34;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;k&#34;&gt;for&lt;/span&gt; USERHOST in &lt;span class=&#34;s2&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span class=&#34;si&#34;&gt;${&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;!HOSTS[@]&lt;/span&gt;&lt;span class=&#34;si&#34;&gt;}&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt; &lt;span class=&#34;k&#34;&gt;do&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  &lt;span class=&#34;nv&#34;&gt;PASSWORD&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span class=&#34;si&#34;&gt;${&lt;/span&gt;&lt;span class=&#34;nv&#34;&gt;HOSTS&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;nv&#34;&gt;$USERHOST&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;]&lt;/span&gt;&lt;span class=&#34;si&#34;&gt;}&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  &lt;span class=&#34;nv&#34;&gt;COMMAND&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;echo &amp;#39;&lt;/span&gt;&lt;span class=&#34;nv&#34;&gt;$PASSWORD&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#39; | sudo -S dnf install -y cronie &amp;amp;&amp;amp;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;s2&#34;&gt;           sudo systemctl enable --now crond &amp;amp;&amp;amp;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;s2&#34;&gt;           echo &amp;#39;*/5 * * * * root echo hello &amp;gt; /tmp/cron_text&amp;#39; | sudo tee -a /etc/crontab&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  &lt;span class=&#34;nb&#34;&gt;echo&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;→ Deploying to &lt;/span&gt;&lt;span class=&#34;nv&#34;&gt;$USERHOST&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;...&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  sshpass -p &lt;span class=&#34;s2&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span class=&#34;nv&#34;&gt;$PASSWORD&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;&lt;/span&gt; ssh &lt;span class=&#34;nv&#34;&gt;$SSH_OPTIONS&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span class=&#34;nv&#34;&gt;$USERHOST&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span class=&#34;nv&#34;&gt;$COMMAND&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;k&#34;&gt;done&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Malin : c&amp;rsquo;est à l&amp;rsquo;intérieur de l&amp;rsquo;itération que se fait l&amp;rsquo;affection de la variable &lt;code&gt;PASSWORD&lt;/code&gt;, en adéquation avec le binôme utilisateur-machine sur lequel on est actuellement, et ensuite la variable &lt;code&gt;COMMAND&lt;/code&gt; intègre le mot de passe variabilisé en inversant l&amp;rsquo;utilisation des guillemets simples et doubles. Du propre dont j&amp;rsquo;apprends beaucoup !&lt;/p&gt;
&lt;p&gt;Voilà, c&amp;rsquo;est ici que s&amp;rsquo;achève ce récit d&amp;rsquo;automatisation. On termine avec quelques titres accrocheurs suggérés par ce même LLM :&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Fini le copier-coller et le SSH manuel, on peut tout à fait orchestrer plusieurs serveurs sans Ansible ni configuration complexe !&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Pourquoi taper la même suite de commandes X fois quand Bash peut le faire pour vous ?&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Apprenez à vous servir de la paresse comme d&amp;rsquo;un levier de développement !&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;😁&lt;/p&gt;
&lt;p&gt;&lt;a href=&#34;https://stallman.org/articles/happy-hacking.html&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;Happy hacking&lt;/a&gt;!&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Edit 2026-04-01 :&lt;/strong&gt; après m&amp;rsquo;être resservi plusieurs fois de ce script, j&amp;rsquo;ai amélioré le système pour que l&amp;rsquo;utilisation de &lt;em&gt;sudo&lt;/em&gt; sur les serveurs puisse se faire sans mot de passe. J&amp;rsquo;en ai profité pour mettre en place la connexion SSH par clé automatisée sans mot de passe.&lt;/p&gt;
&lt;p&gt;Le résultat est une suite de commandes que je copie-colle directement dans le terminal du lab :&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;c1&#34;&gt;# Générer une paire de clés SSH&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;ssh-keygen -t ed25519 -f &lt;span class=&#34;s2&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span class=&#34;nv&#34;&gt;$HOME&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;/.ssh/id_ed25519&amp;#34;&lt;/span&gt; -N &lt;span class=&#34;s2&#34;&gt;&amp;#34;&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;c1&#34;&gt;# Désactiver la vérification stricte des clés d&amp;#39;hôte&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;sudo -S sed -i &lt;span class=&#34;s2&#34;&gt;&amp;#34;/StrictHostKeyChecking/s/^#//;s/ask/no/&amp;#34;&lt;/span&gt; /etc/ssh/ssh_config &lt;span class=&#34;o&#34;&gt;&amp;lt;&amp;lt;&amp;lt;&lt;/span&gt; mjolnir123
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;c1&#34;&gt;# tableau associatif avec les identifiants des 3 serveurs applicatifs&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nb&#34;&gt;declare&lt;/span&gt; -A &lt;span class=&#34;nv&#34;&gt;HOSTS&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=(&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  &lt;span class=&#34;o&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;tony@stapp01&amp;#34;&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;]=&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;Ir0nM@n&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  &lt;span class=&#34;o&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;steve@stapp02&amp;#34;&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;]=&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;Am3ric@&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  &lt;span class=&#34;o&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;banner@stapp03&amp;#34;&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;]=&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;BigGr33n&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;o&#34;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;c1&#34;&gt;# boucle pour copier la clé SSH publique sur les 3 hôtes et configurer sudo en NOPASSWD&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;k&#34;&gt;for&lt;/span&gt; USERHOST in &lt;span class=&#34;s2&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span class=&#34;si&#34;&gt;${&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;!HOSTS[@]&lt;/span&gt;&lt;span class=&#34;si&#34;&gt;}&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt; &lt;span class=&#34;k&#34;&gt;do&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  &lt;span class=&#34;nv&#34;&gt;PASSWORD&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span class=&#34;si&#34;&gt;${&lt;/span&gt;&lt;span class=&#34;nv&#34;&gt;HOSTS&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;nv&#34;&gt;$USERHOST&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;]&lt;/span&gt;&lt;span class=&#34;si&#34;&gt;}&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  sshpass -p &lt;span class=&#34;s2&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span class=&#34;nv&#34;&gt;$PASSWORD&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;&lt;/span&gt; ssh-copy-id &lt;span class=&#34;s2&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span class=&#34;nv&#34;&gt;$USERHOST&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  ssh &lt;span class=&#34;s2&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span class=&#34;nv&#34;&gt;$USERHOST&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;echo &amp;#39;&lt;/span&gt;&lt;span class=&#34;nv&#34;&gt;$PASSWORD&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#39; | sudo -S bash -c &amp;#39;echo %wheel ALL=\(ALL\) NOPASSWD: ALL &amp;gt; /etc/sudoers.d/nopasswd&amp;#39;&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;k&#34;&gt;done&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;J&amp;rsquo;ai &lt;a href=&#34;https://gist.github.com/neitsab/d2a33d054c7d69da1876fe534eab2aa5&#34; target=&#34;_blank&#34; rel=&#34;noopener&#34;&gt;créé un Gist&lt;/a&gt; pour faciliter le partage du script. Commentaires et améliorations bienvenus !&lt;/p&gt;
</description>
    </item>
    
  </channel>
</rss>
