¿Cuál es la forma más limpia de ejecutar ssh y ejecutar varios comandos en Bash?

Ya tengo un agente ssh configurado, y puedo ejecutar comandos en un servidor externo en Bash script haciendo cosas como:

ssh blah_server "ls; pwd;" 

Ahora, lo que realmente me gustaría hacer es ejecutar una gran cantidad de comandos largos en un servidor externo. Encerrar a todos estos entre comillas sería bastante feo, y realmente preferiría evitar ssh’ing varias veces solo para evitar esto.

Entonces, ¿hay alguna manera de que pueda hacer esto de una vez entre paréntesis o algo así? Estoy buscando algo como:

 ssh blah_server ( ls some_folder; ./someaction.sh; pwd; ) 

Básicamente, estaré contento con cualquier solución, siempre y cuando esté limpia.

Editar

Para aclarar, estoy hablando de que esto es parte de un script bash más grande. Es posible que otras personas tengan que lidiar con el script más adelante, así que me gustaría mantenerlo limpio. No quiero tener un script bash con una línea que se vea así:

 ssh blah_server "ls some_folder; ./someaction.sh 'some params'; pwd; ./some_other_action 'other params';" 

porque es extremadamente feo y difícil de leer.

¿Qué tal un documento de Bash Here ?

 ssh otherhost << EOF ls some_folder; ./someaction.sh 'some params' pwd ./some_other_action 'other params' EOF 

Para evitar los problemas mencionados por @Globalz en los comentarios, puede (dependiendo de lo que esté haciendo en el sitio remoto) salirse con la suya reemplazando la primera línea con

 ssh otherhost /bin/bash << EOF 

Tenga en cuenta que puede hacer una sustitución de variables en el documento Aquí, pero es posible que deba ocuparse de los problemas de las citas. Por ejemplo, si cita la "cadena de límite" (es decir, EOF en el EOF anterior), entonces no puede hacer sustituciones de variables. Pero sin citar la cadena de límite, las variables son sustituidas. Por ejemplo, si ha definido $NAME arriba en su script de shell, podría hacer

 ssh otherhost /bin/bash << EOF touch "/tmp/${NAME}" EOF 

y crearía un archivo en el otro otherhost destino con el nombre de lo que haya asignado a $NAME . También se aplican otras reglas sobre las comillas de guiones de shell, pero son demasiado complicadas para entrar aquí.

Edite su script localmente, luego páselo a ssh, por ej.

 cat commands-to-execute-remotely.sh | ssh blah_server 

donde commands-to-execute-remotely.sh parece a su lista anterior:

 ls some_folder ./someaction.sh pwd; 

Veo dos maneras:

Primero haces un socket de control como este:

  ssh -oControlMaster=yes -oControlPath=~/.ssh/ssh-%r-%h-%p  

y ejecuta tus comandos

  ssh -oControlMaster=no -oControlPath=~/.ssh/ssh-%r-%h-%p  -t  

De esta forma puedes escribir un comando ssh sin tener que volver a conectarte al servidor.

El segundo sería generar dinámicamente el script, scp y ejecutarlo.

Para que coincida con su código de muestra, puede ajustar sus comandos dentro de qoutes simples o dobles. Por ejemplo

 ssh blah_server " ls pwd " 

Esto también se puede hacer de la siguiente manera. Pon tus comandos en una secuencia de comandos, vamos a nombrar comandos-inc.sh

 #!/bin/bash ls some_folder ./someaction.sh pwd 

Guarda el archivo

Ahora ejecútalo en el servidor remoto.

 ssh user@remote 'bash -s' < /path/to/commands-inc.sh 

Nunca falló para mí.

SSH y ejecuta múltiples comandos en Bash.

Comandos separados con punto y coma dentro de una cadena, pasados ​​a eco, todos canalizados en el comando ssh. Por ejemplo:

 echo "df -k;uname -a" | ssh 192.168.79.134 Pseudo-terminal will not be allocated because stdin is not a terminal. Filesystem 1K-blocks Used Available Use% Mounted on /dev/sda2 18274628 2546476 14799848 15% / tmpfs 183620 72 183548 1% /dev/shm /dev/sda1 297485 39074 243051 14% /boot Linux newserv 2.6.32-431.el6.x86_64 #1 SMP Sun Nov 10 22:19:54 EST 2013 x86_64 x86_64 x86_64 GNU/Linux 

Ponga todos los comandos en un script y se puede ejecutar como

 ssh @ "bash -s" <./remote-commands.sh 

Esto funciona bien para crear scripts, ya que no tiene que incluir otros archivos:

 #!/bin/bash ssh @ "bash -s" << EOF # here you just type all your commmands, as you can see, ie touch /tmp/test1; touch /tmp/test2; touch /tmp/test3; EOF 

Para cualquiera que se tropiece aquí como yo, tuve éxito al evitar el punto y coma y la nueva línea:

Primer paso: el punto y coma. De esta manera, no rompemos el comando ssh:

 ssh  echo test\;ls ^ backslash! 

Listado de los hosts remotos / directorio de inicio (conectado como root), mientras que

 ssh  echo test;ls ^ NO backslash 

enumeró el directorio de trabajo actual.

Siguiente paso: romper la línea:

  v another backslash! ssh  echo test\;\ ls 

Esto nuevamente enumeró el directorio de trabajo remoto – formato mejorado:

 ssh \ echo test\;\ ls 

Si realmente es más bonito que aquí documentar o citar líneas discontinuas, bueno, no me corresponde a mí decidir …

(Usando bash, Ubuntu 14.04 LTS)

La forma más fácil de configurar su sistema para usar sesiones de ssh individuales de forma predeterminada con multiplexación.

Esto se puede hacer creando una carpeta para los sockets:

 mkdir ~/.ssh/controlmasters 

Y luego agregue lo siguiente a su configuración .ssh:

 Host * ControlMaster auto ControlPath ~/.ssh/controlmasters/%r@%h:%p.socket ControlMaster auto ControlPersist 10m 

Ahora, no necesita modificar ninguno de sus códigos. Esto permite múltiples llamadas a ssh y scp sin crear múltiples sesiones, lo cual es útil cuando se necesita una mayor interacción entre las máquinas locales y remotas.

Gracias a la respuesta de @ terminus, http://www.cyberciti.biz/faq/linux-unix-osx-bsd-ssh-multiplexing-to-speed-up-ssh-connections/ y https://en.wikibooks.org / wiki / OpenSSH / Cookbook / Multiplexing .

Las respuestas publicadas que utilizan cadenas multilínea y varias secuencias de comandos bash no me funcionaron.

  • Las cadenas largas multilíneas son difíciles de mantener.
  • Los scripts bash separados no mantienen variables locales.

Aquí hay una forma funcional de ejecutar ssh y ejecutar varios comandos mientras se mantiene el contexto local.

 LOCAL_VARIABLE=test run_remote() { echo "$LOCAL_VARIABLE" ls some_folder; ./someaction.sh 'some params' ./some_other_action 'other params' } ssh otherhost "$(set); run_remote"