Usar SSH para iniciar un proceso de forma remota

18

He escrito un script que estoy usando para impulsar e implementar un nuevo servicio en varias máquinas bajo mi control, y para ejecutar el proceso estoy usando ssh para iniciar el proceso de forma remota. Desafortunadamente, cada vez que uso SSH para iniciar el proceso, el comando SSH nunca parece regresar, lo que hace que el script se detenga.

El comando se especifica como: ssh $ user @ $ host "/ root / command &". Cada vez que ejecuto comandos simples, como ps o who, el comando SSH regresa inmediatamente, sin embargo, cuando intento iniciar mi proceso, no regresa. He intentado trucos como envolver mi proceso en una secuencia de comandos bash simple que inicia el proceso y luego se cierra, sin embargo, esto también bloquea el comando SSH (incluso si la secuencia de comandos bash tiene un mensaje de éxito y sale normalmente).

¿Alguien tiene alguna idea de lo que está causando este comportamiento y cómo puedo hacer que el comando SSH regrese tan pronto como se haya iniciado el proceso?

Gracias por tus ideas!

rmrobins
fuente
Publique la línea de comando exacta que está utilizando ... omita las contraseñas / nombres de usuario / IPs
Joseph Kern el
ssh $ SSH_USER @ $ HOST_ADDR "/ root / AppName &"
rmrobins el
Debo mencionar que he configurado claves SSH, por lo que no es necesario usar contraseñas para ejecutar comandos en los sistemas remotos.
rmrobins
@rmrobins, un muy buen paso: configurar la autenticación de clave pública.
nik

Respuestas:

28

SSH conecta stdin, stdout y stderr del shell remoto a su terminal local, para que pueda interactuar con el comando que se ejecuta en el lado remoto.

Como efecto secundario, seguirá ejecutándose hasta que se hayan cerrado estas conexiones, lo que ocurre solo cuando el comando remoto y todos sus elementos secundarios (!) Han finalizado (porque los elementos secundarios, que es lo que inicia "&", heredan std * de su proceso principal y mantenerlo abierto).

Entonces necesitas usar algo como

ssh user@host "/script/to/run < /dev/null > /tmp/mylogfile 2>&1 &"

<,> Y 2> & 1 redirigen stdin / stdout / stderr lejos de su terminal. El "&" luego hace que su script pase al fondo. En producción, por supuesto, redirigiría stdin / err a un archivo de registro adecuado.

Ver

http://osdir.com/ml/network.openssh.general/2006-05/msg00017.html

Editar:

Acabamos de descubrir que la < /dev/nullanterior no es necesario (pero redirigir stdout / err es decir ). No tengo idea de por qué ...

sleske
fuente
Gracias, esto es exactamente lo que estaba buscando: no se me ocurrió que el proceso heredaría el estándar * incluso cuando se usa & para iniciarlo en segundo plano.
rmrobins
+1! Funciona para mi. Y también puede imprimir la salida haciendo eco del archivo de registro: ssh user@host "/script/to/run > /tmp/ssh.stdout 2>&1 && cat /tmp/ssh.stdout && rm -f /tmp/ssh.stdout"
Fishdrowned
5

Podrías intentar nohup . Hombre nohup para más detalles.

ssh host "nohup script &"

Si desea mantener la salida en la máquina remota, aquí hay una variante .

ssh user@host 'export REMOTE=myname; nice nohup ./my-restart >
logfile.log 2>&1 &'
Jauder Ho
fuente
5

Otra alternativa sería encender un desapegado screen(1), algo como:

ssh -l user host "screen -d -m mycommand"

Esto iniciará una pantalla separada (que captura toda la interacción dentro de ella) y luego regresará inmediatamente, finalizando la sesión ssh.

Con un poco más de ingenio, puede resolver llamadas de comandos remotos bastante complejas de esta manera.

towo
fuente
4
 -f      Requests ssh to go to background just before command execution.
         This is useful if ssh is going to ask for passwords or
         passphrases, but the user wants it in the background.  This
         implies -n.  The recommended way to start X11 programs at a
         remote site is with something like ssh -f host xterm.

         If the ExitOnForwardFailure configuration option is set to “yes”,
         then a client started with -f will wait for all remote port for‐
         wards to be successfully established before placing itself in the
         background.
Osito de peluche
fuente
1
El problema con este método es que el comando SSH no está realmente terminado, simplemente está oculto en segundo plano, por lo que el host que ejecuta el script tendrá una gran cantidad de comandos SSH en segundo plano que nunca regresan porque los comandos SSH nunca regresan ( es decir, la raíz del problema deseo de resolver)
rmrobins
-1

Creo que la forma correcta sería

ssh user@host exec script.sh &
nik
fuente
No, eso no funciona para mí. ¿Por qué debería hacerlo?
sleske el
No he usado el empuje de fondo sobre ssh, estaba intentando sin un término a mano. culpa mía.
nik