Comment puis-je automatiser l'exécution de commandes à distance via SSH sur plusieurs serveurs en parallèle?

StackOverflow https://stackoverflow.com/questions/243750

  •  04-07-2019
  •  | 
  •  

Question

J'ai cherché un peu autour pour des questions similaires, mais en dehors de l'exécution d'une commande ou peut-être de quelques commandes avec des éléments tels que:

ssh user@host -t sudo su -

Cependant, si j’ai essentiellement besoin d’exécuter un script sur (disons) 15 serveurs à la fois. Est-ce faisable en bash? Dans un monde parfait, je dois éviter, dans la mesure du possible, d'installer des applications pour y parvenir. Par souci d'argumentation, disons simplement que je dois effectuer les opérations suivantes sur 10 hôtes:

  1. Déployer un nouveau conteneur Tomcat
  2. Déployez une application dans le conteneur et configurez-la
  3. Configurer un hôte virtuel Apache
  4. Recharger Apache

J'ai un script qui effectue tout cela, mais il dépend de ma connexion à tous les serveurs, de l'extraction d'un script d'un référentiel, puis de son exécution. Si ce n'est pas faisable à Bash, quelles alternatives suggérez-vous? Ai-je besoin d'un plus gros marteau, tel que Perl (Python pourrait être préféré, car je peux garantir que Python est sur toutes les boîtes dans un environnement RHEL grâce à yum / up2date)? Si quelqu'un peut me signaler des informations utiles, il serait grandement apprécié, en particulier s'il est réalisable en mode bash. Je vais me contenter de Perl ou de Python, mais je ne les connais pas aussi (je travaille dessus). Merci!

Était-ce utile?

La solution

Souvent, je n'utilise que la version originale d'Excl de Tcl. Vous devez seulement avoir cela sur la machine locale. Si je suis dans un programme utilisant Perl, je le fais avec Net :: SSH :: Attendez-vous . D'autres langues ont des & Quot; expect & Quot; similaires outils.

Autres conseils

Vous pouvez exécuter un script local comme indiqué par che et Yang, et / ou utiliser un document Here:

ssh root@server /bin/sh <<\EOF  
wget http://server/warfile    # Could use NFS here  
cp app.war /location  
command 1  
command 2  
/etc/init.d/httpd restart  
EOF 

La question de savoir comment exécuter des commandes sur plusieurs serveurs à la fois est apparue sur une liste de diffusion Perl l'autre jour et je donnerai la même recommandation J'y ai donné , ce qui revient à utiliser gsh:

.

http://outflux.net/unix/software/gsh

gsh est similaire au " for box in box1_name box2_name box3_name " solution déjà indiquée mais j'estime que gsh est plus pratique. Vous configurez un fichier / etc / ghosts contenant vos serveurs dans des groupes tels que web, db, RHEL4, x86_64 ou autre (man ghosts), puis vous utilisez ce groupe lorsque vous appelez gsh.

[pdurbin@beamish ~]$ gsh web "cat /etc/redhat-release; uname -r"
www-2.foo.com: Red Hat Enterprise Linux AS release 4 (Nahant Update 7)
www-2.foo.com: 2.6.9-78.0.1.ELsmp
www-3.foo.com: Red Hat Enterprise Linux AS release 4 (Nahant Update 7)
www-3.foo.com: 2.6.9-78.0.1.ELsmp
www-4.foo.com: Red Hat Enterprise Linux Server release 5.2 (Tikanga)
www-4.foo.com: 2.6.18-92.1.13.el5
www-5.foo.com: Red Hat Enterprise Linux Server release 5.2 (Tikanga)
www-5.foo.com: 2.6.18-92.1.13.el5
[pdurbin@beamish ~]$

Vous pouvez également combiner ou scinder des groupes fantômes, en utilisant par exemple web + db ou web-RHEL4.

Je mentionnerai également que même si je n'ai jamais utilisé shmux, son site Web contient une liste de logiciel (y compris gsh) qui vous permet d’exécuter des commandes sur plusieurs serveurs à la fois. Capistrano a déjà été mentionné et (d'après ce que j'ai compris) pourrait également figurer sur cette liste.

Jetez un coup d'œil à Expect (man expect)

J'ai déjà effectué des tâches similaires à l'aide d'Expect.

Vous pouvez diriger le script local vers le serveur distant et l'exécuter avec une seule commande:

ssh -t user@host 'sh' < path_to_script

Ceci peut être davantage automatisé en utilisant une authentification par clé publique et un encapsulage avec des scripts pour exécuter une exécution en parallèle.

Vous pouvez essayer paramiko . C'est un client SSH pur-python. Vous pouvez programmer vos sessions SSH. Rien à installer sur des machines distantes.

Voir ce excellent article sur la façon de l'utiliser.

Pour vous donner la structure, sans code réel.

  1. Utilisez scp pour copier votre script d'installation / de configuration dans la zone cible.
  2. Utilisez ssh pour appeler votre script sur la boîte distante.

pssh peut être intéressant car, contrairement à la plupart des solutions mentionnées ici, les commandes sont exécutées en parallèle. .

(Pour mon usage personnel, j’ai écrit un petit script plus simple, très similaire à celui de GavinCattell, c’est documenté ici ).

Avez-vous examiné des éléments tels que Puppet ou Cfengine . Ils peuvent faire ce que vous voulez et probablement beaucoup plus.

Pour ceux qui tombent sur cette question, je vais inclure une réponse qui utilise Fabric , qui résout exactement le problème décrit. ci-dessus: Exécution de commandes arbitraires sur plusieurs hôtes via ssh.

Une fois que la structure est installée, vous devez créer un fabfile.py élément et implémenter des tâches pouvant être exécutées sur vos hôtes distants. Par exemple, une tâche pour Recharger Apache pourrait ressembler à ceci:

from fabric.api import env, run

env.hosts = ['host1@example.com', 'host2@example.com']

def reload():
    """ Reload Apache """
    run("sudo /etc/init.d/apache2 reload")

Ensuite, sur votre ordinateur local, exécutez fab reload et la commande sudo /etc/init.d/apache2 reload sera exécutée sur tous les hôtes spécifiés dans env.hosts.

Vous pouvez le faire de la même manière que vous l'avez fait auparavant, il vous suffit de le scripter au lieu de le faire manuellement. Le code suivant est connecté à la machine nommée 'loca' et y exécute deux commandes. Ce que vous devez faire, c'est simplement insérer les commandes que vous voulez y exécuter.

che@ovecka ~ $ ssh loca 'uname -a; echo something_else'
Linux loca 2.6.25.9 #1 (blahblahblah)
something_else

Ensuite, pour parcourir toutes les machines, procédez comme suit:

for box in box1_name box2_name box3_name
do
   ssh $box 'commmands_to_run_everywhere'
done

Pour que cette chose ssh fonctionne sans entrer les mots de passe en permanence, vous devez configurer l'authentification par clé. Vous pouvez en apprendre davantage à ce sujet à l'adresse du site de développement IBM .

Vous pouvez exécuter la même commande sur plusieurs serveurs à la fois avec un outil tel que cluster ssh . Le lien est vers une discussion de cluster ssh sur le blog du paquet Debian du jour.

Eh bien, pour les étapes 1 et 2, n’existe-t-il pas d’interface Web de gestionnaire Tomcat; vous pouvez écrire un script avec curl ou zsh avec le plug in libwww.

Pour SSH, vous cherchez à: 1) ne pas être invité à entrer un mot de passe (utilisez les clés) 2) transmettez la (les) commande (s) sur la ligne de commande de SSH, ce qui est similaire à rsh sur un réseau approuvé.

D'autres publications vous ont montré quoi faire, et j'utiliserais probablement aussi sh mais je serais tenté d'utiliser perl comme ssh tomcatuser@server perl -e 'do-everything-on-one-line;' ou vous pourriez le faire:

soit scp the_package.tbz tomcatuser@server:the_place/.
ssh tomcatuser@server /bin/sh <<\EOF
définir des éléments comme TOMCAT_WEBAPPS=/usr/local/share/tomcat/webapps
tar xj the_package.tbz ou rsync rsync://repository/the_package_place
mv $TOMCAT_WEBAPPS/old_war $TOMCAT_WEBAPPS/old_war.old
mv $THE_PLACE/new_war $TOMCAT_WEBAPPS/new_war
touch $TOMCAT_WEBAPPS/new_war [vous n'êtes normalement pas obligé de redémarrer tomcat]
mv $THE_PLACE/vhost_file $APACHE_VHOST_DIR/vhost_file
$APACHECTL restart [Il peut être nécessaire de se connecter en tant qu'utilisateur Apache pour déplacer ce fichier et le redémarrer]

EOF

Vous voulez DSH ou un shell distribué, qui est souvent utilisé dans les clusters. Voici le lien: dsh

Vous avez essentiellement des groupes de noeuds (un fichier contenant une liste de noeuds) et vous spécifiez le groupe de noeuds sur lequel vous souhaitez exécuter des commandes, puis vous utiliserez dsh, comme si vous utilisiez ssh pour les exécuter.

dsh -a /path/to/some/command/or/script

Il exécutera la commande sur toutes les machines en même temps et renverra la sortie préfixée avec le nom d'hôte. La commande ou le script doit être présent sur le système, un répertoire NFS partagé peut donc être utile pour ce genre de choses.

Crée la commande ssh hostname de toutes les machines consultées. par Quierati http://pastebin.com/pddEQWq2

#Use in .bashrc
#Use "HashKnownHosts no" in ~/.ssh/config or /etc/ssh/ssh_config 
# If known_hosts is encrypted and delete known_hosts

[ ! -d ~/bin ] && mkdir ~/bin
for host in `cut -d, -f1 ~/.ssh/known_hosts|cut -f1 -d " "`;
  do
    [ ! -s ~/bin/$host ] && echo ssh $host '$*' > ~/bin/$host
done
[ -d ~/bin ] && chmod -R 700 ~/bin
export PATH=$PATH:~/bin 

Ex Execute:

$for i in hostname{1..10}; do $i who;done

Il existe un outil appelé FLATT (outil d'automatisation et de dépannage FLexible) qui vous permet d'exécuter des scripts sur plusieurs systèmes Unix / Linux. hôtes avec un clic d'un bouton. C'est une application graphique de bureau qui fonctionne sur Mac et Windows, mais il existe également un client java en ligne de commande.
Vous pouvez créer des travaux par lots et les réutiliser sur plusieurs hôtes.
Nécessite Java 1.6 ou une version ultérieure.

Bien que ce soit un sujet complexe, je vous recommande vivement de Capistrano .

Je ne sais pas si cette méthode fonctionnera pour tout ce que vous voulez, mais vous pouvez essayer quelque chose comme ceci:

$ cat your_script.sh | ssh your_host bash

Qui exécutera le script (qui réside localement) sur le serveur distant.

Multixterm est très bien pour cela, et vous permet de placer facilement le 1 sur 1 machine en séquence.

Il suffit de lire un nouveau blog en utilisant setsid sans autre installation / configuration que le noyau principal. Testé / Vérifié sous Ubuntu14.04.

Alors que l'auteur a une explication très claire et un exemple de code, voici la partie magique pour un rapide coup d'œil:

#----------------------------------------------------------------------
# Create a temp script to echo the SSH password, used by SSH_ASKPASS
#----------------------------------------------------------------------
SSH_ASKPASS_SCRIPT=/tmp/ssh-askpass-script
cat > ${SSH_ASKPASS_SCRIPT} <<EOL
#!/bin/bash
echo "${PASS}"
EOL
chmod u+x ${SSH_ASKPASS_SCRIPT}

# Tell SSH to read in the output of the provided script as the password.
# We still have to use setsid to eliminate access to a terminal and thus avoid
# it ignoring this and asking for a password.
export SSH_ASKPASS=${SSH_ASKPASS_SCRIPT}
......
......
# Log in to the remote server and run the above command.
# The use of setsid is a part of the machinations to stop ssh 
# prompting for a password.
setsid ssh ${SSH_OPTIONS} ${USER}@${SERVER} "ls -rlt"

Voici un script pour exécuter une commande SSH sur plusieurs machines, cela peut aider:

#!/bin/bash
MACHINES="machine1 machine2 machine3 machine4 machine5 machine6"
for m in $MACHINES
do
        cmd="ssh $m '$*'"
        eval $cmd
done

Vous pouvez même mettre ceci afin qu'il soit dans votre chemin, appelez-le comme sshAll, puis tapez simplement la commande sshAll.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top