Proceso de muerte generado por ssh cuando ssh muere

23

Esta es una pregunta que se ha abordado varias veces, no solo aquí, sino también en otros sitios de la red de intercambio de pila (por ejemplo, ¿Cómo hacer que ssh mate el proceso remoto cuando interrumpo ssh? ). Sin embargo, no puedo hacer que ninguna de las soluciones funcione para mí.

Estoy ejecutando un comando a través de ssh. Cada vez que salgo de ssh, quiero que el comando también muera. Este comando es un demonio llamado ktserver que se ejecuta indefinidamente hasta que presione Ctrl-C.

Lo ejecuto de la siguiente manera: ssh -t compute-0-1 ktservery, de hecho, cuando presiono Ctrl-C, el proceso finaliza con gracia y la sesión ssh finaliza.

Sin embargo, si en lugar de presionar Ctrl-C, elimino el proceso ssh usando el killcomando (por ejemplo, enviando SIGINT o SIGHUP), el ktserverproceso permanece vivo.

¿Cómo puedo hacer que el ktserversiempre muera independientemente de cómo sshse mata?

EDITAR : si, en lugar de ktserverejecutar algo completamente diferente, como gedit, todo funciona como un encanto (es decir, gedit muere cuando la conexión muere). Por lo tanto, puede haber algo mal con el proceso en sí. Por ejemplo, pensé que podría estar ignorando SIGHUP o SIGINT. Sin embargo, cuando ejecuto kill -1 ktservero kill -2 ktserver, el proceso muere como se esperaba.

EDIT2 : Como señala Mark Plotnick, el problema está relacionado con el hecho de que no hay comunicación circulando en el canal ssh. Lo he confirmado ejecutando ssh -t <host> ready matando el proceso ssh después. readseguía vivo y pateando.

GermanK
fuente
¿Lo has intentado kill -9 ktserver?
@HermanTorjussen Claro, eso funciona. El problema es que este comando se ejecuta desde otro proceso y es posible que no tenga control sobre todas las posibilidades que pueden causar la muerte de mi proceso y, por lo tanto, la sesión ssh con él. Por lo tanto, necesito una forma confiable de asegurarme de que cada vez que mi proceso, y por lo tanto se oculta, ktserver muera con ellos.
AlemánK
Mi experiencia con Linux es que si el comando remoto no realiza ninguna E / S a la conexión TCP inactiva, seguirá ejecutándose. He ssh example.com dd ...completado los trabajos incluso horas después de que la sshconexión falle debido a problemas de red. Si puede modificar ktserverpara tomar una opción para generar algo de vez en cuando, eso puede ser una solución.
Mark Plotnick
@MarkPlotnick De hecho, he intentado ejecutar readen la computadora remota, y después de cerrar la conexión ssh, readno morí. Desafortunadamente, no puedo cambiar ktserver para generar nada. ¿No hay solución entonces?
GermanK
2
Supongo que cuando ssh muere, tu caparazón también muere. Puede configurar su shell para enviar una señal -1 (SIGHUP) cuando termina. ( shopt -s huponexit) ¿Puedes probar si esto funciona para ti?
Hennes

Respuestas:

13

Por lo general, cuando la conexión ssh muere, el shell también muere. Puede configurar su shell para enviar una señal -1 (SIGHUP) cuando termina a todos sus hijos.

Para bash, puede configurar esta opción a través del comando incorporado shopt . ( shopt -s huponexit)

Por zsh que quieras .setoptHUP

Hennes
fuente
Pensé que esta era la respuesta a mi problema actual, pero no parece funcionar. Estoy ejecutando: ssh $ host "scp LargeFile.dat $ OtherHost: / tmp" & pid = $! y luego tratando de detener esa transferencia con: shopt -s huponexit; kill $ pid, pero el scp no se detiene cuando mato el ssh que comencé. ¿Alguna idea?
David Doria
¿Puedes probar con las opciones de shell establecidas antes de iniciar el comando scp? ¿O iniciando un shell, configurando shopt y comenzando scp?
Hennes
2
Esto funciona para mí, pero primero tuve que asegurarme de que estaba usando ssh -t -t, (¡aviso -tdos veces!) Lo que fuerza la asignación de tty, en lugar de solo pty.
Nicolas Wu
13

Encontré eso simplemente usando -t -tcomo argumento para sshhacerlo funcionar. No tuve que configurar huponexitni el shell de origen ni el remoto.

Probé esto de la siguiente manera:

No funciona

ssh user@remote sleep 100
^C

Esto mató la sesión ssh, pero puedo ver que el proceso de suspensión aún se está ejecutando en el host remoto (lo ps -ef | grep sleepmuestra).

Funciona:

ssh -t -t user@remote sleep 100
^C

Esto mata la sesión ssh y también se eliminó el proceso de suspensión remota. También he verificado que la señal que se envía al proceso remoto es SIGINTsi usa Control- C. También verifiqué que SIGKILL (-9) aplicado al sshproceso también eliminará el proceso remoto.

EDITAR 1:

Eso fue cierto para sleep... para procesos remotos más obstinados, descubrí que sshmaneja ^ C de manera diferente que SIGINT. Ctrl- Cfuncionó, pero no lo kill -INT $pidhizo.

Esto es lo que finalmente se me ocurrió que funcionó para mi aplicación real (robando de las otras respuestas).

ssh -t -t -i id_rsa user@mic0 "/bin/sh -O huponexit -c 'sleep 100'"

Tenga en cuenta el uso anidado de comillas dobles y comillas simples. ¡Tenga en cuenta que su proceso remoto DEBE responder a SIGHUP saliendo realmente!

Mark Lakata
fuente
Esto funcionó mejor para mí, pero para su información, también causó que los caracteres de control de terminal se desangraran, lo que puede causar una salida divertida. Entonces, la solución fácil en mi caso fue ajustar los comandos llamados y canalizar su salida cat. Por ejemplo,ssh -ttq user@host '{ cmd; cmd; } | cat'
Droj
Ctrl-CNO siempre es equivalente a kill -INT $pid, vea mi respuesta en unix.stackexchange.com/questions/377191/… y otra en stackoverflow.com/questions/8398845/… para los detalles sangrientos ;-)
thecarpy
@thecarpy: su primera respuesta dice que Ctrl-C es similar a SIGINT , y la otra respuesta dice que ^Cenvía SIGINT . Entonces, ¿cuál es la diferencia exacta si no son equivalentes?
Mark Lakata
1

Si ssh no propaga señales, recibe ¿qué esperarías de él?

UPD (especial para JosephR): obviamente es un error en cuestión que se deriva de un malentendido: "El proceso de eliminación se genera por ssh cuando ssh muere". SSH generalmente no genera procesos (a veces lo hace, pero esta es otra historia), SSHD sí lo hace, cuando miramos el otro lado de la conexión. SSH simplemente se basa en la abstracción pseudo-terminal que tiene el servidor remoto. Es por eso que lo único que puede ser de ayuda es la capacidad del terminal para emitir señales a sus procesos adjuntos. Esto es algo muy básico para todos los sistemas tipo UNIX.

poige
fuente
1
Esto no proporciona una respuesta a la pregunta. Para criticar o solicitar una aclaración de un autor, deje un comentario debajo de su publicación.
Anthon
@Anthon, es una explicación. Pero nadie dice que esta debería ser la única respuesta correcta. Gracias por tu comentario a continuación.
poige
1
@poige Quizás desarrolle la explicación para que pueda ser útil para el OP y otros.
Joseph R.
@JosephR., Ok, solo para ti.
poige
1
Si digo "Proceso de eliminación generado por sshd cuando se pierde la conexión ssh", ¿le parecería mejor? No creo que la reformulación resuelva mi problema de ninguna manera.
AlemánK
0

La solución publicada aquí no funcionó para mí, pero como esta pregunta surgió primero cuando estaba buscando una solución a un problema similar y también -t -tse mencionó el truco aquí, publicaré una solución que funcionó para mí para que otros la intenten.

ssh -t -t -o ControlMaster=auto -o ControlPath='~/test.ssh' your_remote_ip_goes_here "your_long_running_command" &
sleep 100
ssh -o ControlPath='~/test.ssh' -O exit your_remote_ip_goes_here

Mi comando de larga ejecución ya no se estaba ejecutando cuando la conexión se terminó así.

Greg0ry
fuente