Pregunta ¿Cómo usar SSH para ejecutar un script de shell en una máquina remota?


Tengo que ejecutar un script de shell (Windows / Linux) en una máquina remota.

Tengo SSH configurado en la máquina A y B. Mi script está en la máquina A, que ejecutará parte de mi código en una máquina remota, la máquina B.

Las computadoras locales y remotas pueden ser sistemas basados ​​en Windows o Unix.

¿Hay alguna forma de ejecutar esto usando plink / ssh?


1010
2017-11-20 11:44


origen


Respuestas:


Si la Máquina A es un cuadro de Windows, puede usar Plink (parte de Masilla) con el parámetro -m, y ejecutará el script local en el servidor remoto.

plink root@MachineB -m local_script.sh

Si la Máquina A es un sistema basado en Unix, puede usar:

ssh root@MachineB 'bash -s' < local_script.sh

No debería tener que copiar el script al servidor remoto para ejecutarlo.


1025
2018-04-28 20:41



Esta es una vieja pregunta, y la respuesta de Jason funciona bien, pero me gustaría añadir esto:

ssh user@host <<'ENDSSH'
#commands to run on remote host
ENDSSH

Esto también se puede usar con su y comandos que requieren la entrada del usuario. (nota la ' escapado heredoc)

Editar: Dado que esta respuesta sigue recibiendo bits de tráfico, agregaría aún más información a este maravilloso uso de heredoc:

Puede anidar comandos con esta sintaxis, y esa es la única forma en que el anidamiento parece funcionar (de una manera sensata)

ssh user@host <<'ENDSSH'
#commands to run on remote host
ssh user@host2 <<'END2'
# Another bunch of commands on another host
wall <<'ENDWALL'
Error: Out of cheese
ENDWALL
ftp ftp.secureftp-test.com <<'ENDFTP'
test
test
ls
ENDFTP
END2
ENDSSH

En realidad, puedes tener una conversación con algunos servicios como telnet, ftp, etc. Pero recuerda que heredoc simplemente envía el stdin como texto, no espera la respuesta entre líneas

Editar: descubrí que puedes sangrar el interior si usas <<-END !

ssh user@host <<-'ENDSSH'
    #commands to run on remote host
    ssh user@host2 <<-'END2'
        # Another bunch of commands on another host
        wall <<-'ENDWALL'
            Error: Out of cheese
        ENDWALL
        ftp ftp.secureftp-test.com <<-'ENDFTP'
            test
            test
            ls
        ENDFTP
    END2
ENDSSH

(Creo que esto debería funcionar)

Ver también http://tldp.org/LDP/abs/html/here-docs.html


506
2017-10-06 13:11



Además, no se olvide de las variables de escape si desea recogerlos desde el host de destino.

Esto me ha sorprendido en el pasado.

Por ejemplo:

user@host> ssh user2@host2 "echo \$HOME"

imprime / home / user2

mientras

user@host> ssh user2@host2 "echo $HOME"

imprime / home / usuario

Otro ejemplo:

user@host> ssh user2@host2 "echo hello world | awk '{print \$1}'"

imprime "hola" correctamente.


212
2017-11-20 12:25



Esta es una extensión de la respuesta de YarekT para combinar comandos remotos en línea con pasar variables ENV de la máquina local al host remoto para que pueda parametrizar sus scripts en el lado remoto:

ssh user@host ARG1=$ARG1 ARG2=$ARG2 'bash -s' <<'ENDSSH'
  # commands to run on remote host
  echo $ARG1 $ARG2
ENDSSH

Encontré esto excepcionalmente útil al mantenerlo todo en una secuencia de comandos por lo que es muy legible y mantenible.

Por qué esto funciona ssh admite la siguiente sintaxis:

ssh user @ host remote_command

En bash podemos especificar variables de entorno para definir antes de ejecutar un comando en una sola línea, como por ejemplo:

ENV_VAR_1 = 'value1' ENV_VAR_2 = 'value2' bash -c 'echo $ ENV_VAR_1 $ ENV_VAR_2'

Eso hace que sea fácil definir variables antes de ejecutar un comando. En este caso, echo es nuestro comando que estamos ejecutando. Todo antes del eco define variables de entorno.

Así que combinamos esas dos características y la respuesta de YarekT para obtener:

ssh user @ host ARG1 = $ ARG1 ARG2 = $ ARG2 'bash -s' << 'ENDSSH' ...

En este caso, estamos configurando ARG1 y ARG2 a valores locales. Enviando todo después de user @ host como remote_command. Cuando la máquina remota ejecuta el comando ARG1 y ARG2 se establecen los valores locales, gracias a la evaluación de línea de comando local, que define las variables de entorno en el servidor remoto, y luego ejecuta el comando bash -s usando esas variables. Voila.


124
2017-09-09 15:00



<hostA_shell_prompt>$ ssh user@hostB "ls -la"

Esto le solicitará una contraseña, a menos que haya copiado la clave pública de su usuario hostA en el archivo authorized_keys en la página de inicio del directorio .ssh del usuario. Eso permitirá la autenticación sin contraseña (si se acepta como un método de autenticación en la configuración del servidor ssh)


89
2017-11-20 11:53



Comencé a usar Tela para operaciones más sofisticadas. Fabric requiere Python y un par de otras dependencias, pero solo en la máquina cliente. El servidor solo necesita ser un servidor ssh. Encuentro que esta herramienta es mucho más poderosa que los scripts de shell entregados a SSH, y bien vale la pena la molestia de configurarlo (especialmente si disfrutas de la programación en Python). Fabric maneja secuencias de comandos en múltiples hosts (o hosts de ciertos roles), ayuda a facilitar las operaciones idempotentes (como agregar una línea a un script de configuración, pero no si ya está allí), y permite la construcción de lógica más compleja (como el Python) el lenguaje puede proporcionar).


24
2018-01-26 16:17



Suponiendo que quiere decir que quiere hacer esto automáticamente desde una máquina "local", sin iniciar sesión manualmente en la máquina "remota", debe buscar en una extensión TCL conocida como Esperar, que está diseñada precisamente para este tipo de situación. La página de inicio a continuación parece un poco asquerosa, pero no dejes que eso te disuada; También proporcioné un enlace a un script para iniciar sesión / interactuar a través de SSH.

http://expect.nist.gov/

http://bash.cyberciti.biz/security/expect-ssh-login-script/


8
2017-11-20 12:10



Prueba correr ssh user@remote sh ./script.unx.


7
2017-12-18 21:16



La respuesta aquí (https://stackoverflow.com/a/2732991/4752883) funciona muy bien si Está intentando ejecutar un script en una máquina Linux remota usando plink o ssh. Funcionará si el script tiene múltiples líneas en linux.

** Sin embargo, si está tratando de ejecutar un script por lotes ubicado en un local linux/windows máquina y su máquina remota es Windowsy consiste de múltiples líneas usando **

plink root@MachineB -m local_script.bat

no funcionará

Solo se ejecutará la primera línea del script. Esto es probablemente un limitación de plink.

Solución 1:

Para ejecutar un script por lotes de varias líneas (especialmente si es relativamente simple, que consiste en unas pocas líneas):

Si su script por lotes original es el siguiente

cd C:\Users\ipython_user\Desktop 
python filename.py

puede combinar las líneas usando el separador "&&" de la siguiente manera en su local_script.bat archivo: https://stackoverflow.com/a/8055390/4752883:

cd C:\Users\ipython_user\Desktop && python filename.py

Después de este cambio, puede ejecutar la secuencia de comandos como se indica aquí por @ JasonR.Coombs: https://stackoverflow.com/a/2732991/4752883 con:

`plink root@MachineB -m local_script.bat`

Solución 2:

Si su script por lotes es relativamente complicado, puede ser mejor usar un lote secuencia de comandos que encapsula el comando plink y sigue como se indica aquí por @Martin https://stackoverflow.com/a/32196999/4752883:

rem Open tunnel in the background
start plink.exe -ssh [username]@[hostname] -L 3307:127.0.0.1:3306 -i "[SSH
key]" -N

rem Wait a second to let Plink establish the tunnel 
timeout /t 1

rem Run the task using the tunnel
"C:\Program Files\R\R-3.2.1\bin\x64\R.exe" CMD BATCH qidash.R

rem Kill the tunnel
taskkill /im plink.exe

0
2018-04-21 00:44



Esta secuencia de comandos bash realiza ssh en una máquina remota de destino y ejecuta algún comando en la máquina remota, no olvide instalar esperar antes de ejecutarlo (en mac brew install expect )

#!/usr/bin/expect
set username "enterusenamehere"
set password "enterpasswordhere"
set hosts "enteripaddressofhosthere"
spawn ssh  $username@$hosts
expect "$username@$hosts's password:"
send -- "$password\n"
expect "$"
send -- "somecommand on target remote machine here\n"
sleep 5
expect "$"
send -- "exit\n"

0
2018-05-30 09:22



Primero, copie el script en la Máquina B usando scp

[usuario @ máquinaA] $ scp / ruta / a / script usuario @ máquinaB: / home / usuario / ruta

Entonces, solo ejecuta el script

[usuario @ máquinaA] $ usuario ssh @ máquinaB "/ home / usuario / ruta / script"

Esto funcionará si ha otorgado permisos ejecutables al script.


-22