¿Cómo puedo automatizar la ejecución de comandos de forma remota a través de SSH en varios servidores en paralelo?

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

  •  04-07-2019
  •  | 
  •  

Pregunta

He buscado un poco preguntas similares, pero además de ejecutar un comando o quizás algunos comandos con elementos como:

ssh user@host -t sudo su -

Sin embargo, ¿qué pasa si básicamente necesito ejecutar un script en (digamos) 15 servidores a la vez?¿Es esto factible en bash?En un mundo perfecto, debo evitar instalar aplicaciones, si es posible, para lograrlo.Por el bien del argumento, digamos que necesito hacer lo siguiente en 10 hosts:

  1. Implementar un nuevo contenedor Tomcat
  2. Implementar una aplicación en el contenedor y configurarla
  3. Configurar un servidor virtual Apache
  4. Recargar Apache

Tengo un script que hace todo eso, pero depende de que inicie sesión en todos los servidores, extraiga un script de un repositorio y luego lo ejecute.Si esto no es factible en bash, ¿qué alternativas sugieres?¿Necesito un martillo más grande, como Perl (podría preferirse Python ya que puedo garantizar que Python está en todas las cajas en un entorno RHEL gracias a yum/up2date)?Si alguien puede indicarme alguna información útil, se lo agradecería mucho, especialmente si es factible en bash.Me conformaré con Perl o Python, pero no los conozco tan bien (estoy trabajando en eso).¡Gracias!

¿Fue útil?

Solución

A menudo, solo usaré la versión Tcl original de Expect. Solo necesita tener eso en la máquina local. Si estoy dentro de un programa usando Perl, hago esto con Net :: SSH :: Esperar . Otros idiomas tienen & Quot; esperar & Quot; herramientas.

Otros consejos

Puede ejecutar un script local como lo muestran che y Yang, y / o puede usar un documento Aquí:

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 

El problema de cómo ejecutar comandos en muchos servidores a la vez apareció en una lista de correo de Perl el otro día y le daré la misma recomendación Di allí , que es usar gsh:

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

gsh es similar a " for box in box1_name box2_name box3_name " La solución ya se proporcionó pero creo que gsh es más conveniente. Configura un archivo / etc / ghosts que contiene sus servidores en grupos como web, db, RHEL4, x86_64 o lo que sea (man ghosts) y luego usa ese grupo cuando llama a 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 ~]$

También puede combinar o dividir grupos fantasma, utilizando web + db o web-RHEL4, por ejemplo.

También mencionaré que aunque nunca he usado shmux, su sitio web contiene una lista de software (incluido gsh) que le permite ejecutar comandos en muchos servidores a la vez. Capistrano ya se ha mencionado y (por lo que entiendo) también podría estar en esa lista.

Eche un vistazo a Expect (man expect)

He realizado tareas similares en el pasado usando Expect.

Puede canalizar el script local al servidor remoto y ejecutarlo con un comando:

ssh -t user@host 'sh' < path_to_script

Esto se puede automatizar aún más mediante el uso de la autenticación de clave pública y el ajuste con scripts para realizar una ejecución paralela.

Puede probar paramiko . Es un cliente ssh puro de Python. Puedes programar tus sesiones ssh. Nada que instalar en máquinas remotas.

Vea este gran artículo sobre cómo usarlo.

Para darle la estructura, sin código real.

  1. Use scp para copiar su script de instalación / configuración en el cuadro de destino.
  2. Use ssh para invocar su secuencia de comandos en el cuadro remoto.

pssh puede ser interesante ya que, a diferencia de la mayoría de las soluciones mencionadas aquí, los comandos se ejecutan en paralelo .

(Para mi propio uso, escribí un pequeño script más simple muy similar al de GavinCattell, es documentado aquí - en francés ).

¿Ha visto cosas como Puppet o Cfengine . Pueden hacer lo que quieras y probablemente mucho más.

Para aquellos que se topan con esta pregunta, incluiré una respuesta que usa Tela, que resuelve exactamente el problema descrito anteriormente:Ejecutar comandos arbitrarios en múltiples hosts a través de ssh.

Una vez instalada la tela, crearías un fabfile.py, e implementar tareas que se puede ejecutar en sus hosts remotos.Por ejemplo, una tarea para Recargar Apache podría verse así:

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")

Luego, en su máquina local, ejecute fab reload y el sudo /etc/init.d/apache2 reload El comando se ejecutará en todos los hosts especificados en env.hosts.

Puede hacerlo de la misma manera que antes, simplemente escríbalo en lugar de hacerlo manualmente. El siguiente código se dirige a la máquina llamada 'loca' y ejecuta dos comandos allí. Lo que debe hacer es simplemente insertar los comandos que desea ejecutar allí.

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

Luego, para recorrer todas las máquinas, haga algo como:

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

Para hacer que esta cosa ssh funcione sin ingresar contraseñas todo el tiempo, deberá configurar la autenticación de clave. Puede leer sobre ello en IBM developerworks .

Puede ejecutar el mismo comando en varios servidores a la vez con una herramienta como cluster ssh . El enlace es a una discusión de cluster ssh en el blog del paquete del día de Debian.

Bueno, para los pasos 1 y 2 no hay una interfaz web de Tomcat Manager; puede escribir eso con curl o zsh con el complemento libwww.

Para SSH estás buscando: 1) no se le solicite una contraseña (use las teclas) 2) pase los comandos en la línea de comandos de SSH, esto es similar a rsh en una red confiable.

Otras publicaciones le han mostrado qué hacer, y probablemente usaría sh también, pero estaría tentado a usar perl como ssh tomcatuser@server perl -e 'do-everything-on-one-line;' o podría hacer esto:

bien scp the_package.tbz tomcatuser@server:the_place/.
ssh tomcatuser@server /bin/sh <<\EOF
define cosas como TOMCAT_WEBAPPS=/usr/local/share/tomcat/webapps
tar xj the_package.tbz o 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 [normalmente no tiene que reiniciar tomcat]
mv $THE_PLACE/vhost_file $APACHE_VHOST_DIR/vhost_file
$APACHECTL restart [podría necesitar iniciar sesión como usuario de apache para mover ese archivo y reiniciar]
EOF

Desea DSH o shell distribuido, que se usa mucho en clústeres. Aquí está el enlace: dsh

Básicamente tiene grupos de nodos (un archivo con listas de nodos en ellos) y especifica en qué grupo de nodos desea ejecutar comandos, luego usaría dsh, como si fuera ssh para ejecutar comandos en ellos.

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

Ejecutará el comando en todas las máquinas al mismo tiempo y devolverá el resultado prefijado con el nombre de host. El comando o script debe estar presente en el sistema, por lo que un directorio NFS compartido puede ser útil para este tipo de cosas.

Crea el comando ssh de hostname de todas las máquinas a las que se accede. por 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 

Ejecutar ex:

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

Existe una herramienta llamada FLATT (Herramienta de Automatización y Solución de Problemas FLexible) que le permite ejecutar scripts en múltiples Unix / Linux hosts con un clic de un botón. Es una aplicación GUI de escritorio que se ejecuta en Mac y Windows, pero también hay un cliente Java de línea de comandos.
Puede crear trabajos por lotes y reutilizarlos en varios hosts.
Requiere Java 1.6 o superior.

Aunque es un tema complejo, le recomiendo encarecidamente Capistrano .

No estoy seguro de si este método funcionará para todo lo que desee, pero puede intentar algo como esto:

$ cat your_script.sh | ssh your_host bash

Que ejecutará el script (que reside localmente) en el servidor remoto.

Multixterm es genial para hacer esto, y le permite poner fácilmente el 1 de n máquina de nuevo en secuencia.

Simplemente lea un nuevo blog utilizando setsid sin ninguna instalación / configuración adicional además del núcleo principal. Probado / verificado en Ubuntu14.04.

Si bien el autor también tiene una explicación muy clara y un código de muestra, aquí está la parte mágica para un vistazo rápido:

#----------------------------------------------------------------------
# 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"

Aquí hay un script para hacer un comando SSH en varias máquinas, puede ayudar:

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

Incluso podría poner esto para que esté en su camino, llamarlo algo así como sshAll, luego simplemente escriba el comando sshAll.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top