Quiero poder enviar señales (SIGINT es lo más importante) a través de ssh.
Este comando:
ssh server "sleep 1000;echo f" > foo
comenzará a dormir en el servidor y después de 1000 segundos colocará 'f \ n' en el archivo foo en mi máquina local. Si presiono CTRL-C (es decir, enviar SIGINT a ssh) matará ssh, pero no matará el modo de suspensión en el servidor remoto. Quiero que mate el sueño en el servidor remoto.
Entonces intenté:
ssh server -t "sleep 1000;echo f" > foo
Pero si stdin no es un terminal me sale este error:
Pseudo-terminal will not be allocated because stdin is not a terminal.
y luego SIGINT todavía no se reenvía.
Entonces intenté:
ssh server -t -t "sleep 1000;echo f" > output
Pero entonces la salida en foo no es 'f \ n' sino 'f \ r \ n', lo cual es desastroso en mi situación (ya que mi salida son datos binarios).
En lo anterior utilizo "sleep 1000; echo f", pero en realidad lo proporciona el usuario, por lo que puede contener cualquier cosa. Sin embargo, si podemos hacer que funcione para "dormir 1000; echo f", lo más probable es que funcione para todas las situaciones realistas.
Realmente no me importa obtener un pseudo terminal en el otro extremo, pero no he podido encontrar ninguna otra forma de obtener ssh para reenviar mi SIGINT.
¿Hay otra manera?
Editar:
El usuario podría dar comandos que lean datos binarios de stdin, como:
seq 1000 | gzip | ssh server "zcat|bzip2; sleep 1000" | bzcat > foo
El usuario podría dar comandos que requieran un uso intensivo de la CPU, como:
ssh server "timeout 1000 burnP6"
Edit2:
La versión que parece funcionar para mí es:
your_preprocessing |
uuencode a | ssh -tt -oLogLevel=quiet server "stty isig -echoctl -echo ; uudecode -o - |
your_command |
uuencode a" | uudecode -o - |
your_postprocessing
Gracias a digital_infinity por señalarme en la dirección correcta.
ssh
debe ser más complicado de lo que muestra como ejemplos, porque puede obtener el comportamiento que desea con una simple reorganización:sleep 1000 && ssh server "echo f" > foo
(Tiene que ser&&
, no;
, para que matarsleep
evite que elssh
comando se ejecute). Tengo razón, haga que sus ejemplos sean más representativos de su uso real, de modo que se pueda dar una mejor respuesta.Respuestas:
Respuesta corta:
y pare el programa con CTRL + N.
Larga explicación:
stty
opciónintr
para cambiar su servidor o el carácter de interrupción local para que no choquen entre sí. En el comando anterior, he cambiado el carácter de interrupción del servidor a CTRL + N. Puede cambiar su carácter de interrupción local y dejar el del servidor sin ningún cambio.stty -echoctl
.stty isig
SIGINT
señaltrap '/bin/true' SIGINT
con una declaración vacía. Sin la trampa no tendrás ningún stdout después de la señal SIGINT de tu parte.fuente
seq 1000 | gzip | ssh -tt dell-test "zcat|bzip2" | bzcat > foo
tampoco funciona. Para que este comando funcione, debemos eliminarlo-tt
. Por lo tanto, la asignación de pseudo terminal probablemente toma algo de entrada de stdin(sleep 1; seq 1000 ) | gzip | uuencode bin | ssh -tt dell-test "stty isig intr ^N -echoctl -echo ; trap '/bin/true' SIGINT; sleep 1; uudecode -o /dev/stdout | zcat |bzip2 | uuencode bin2 " | uudecode -o /dev/stdout | bzcat >foo
. Aunque el carácter de interrupción no funciona, necesitamos algún método de transmisión para el carácter de interrupción mientras stdin está ocupado .Probé todas las soluciones y esta fue la mejor:
/programming/3235180/starting-a-process-over-ssh-using-bash-and-then-killing-it-on-sigint/25882610#25882610
fuente
sleep
proceso en caso de que se pierda la conexión.sleep
, ¿no? He agregado algunosdate >> /tmp/killed
después delcat
, pero no se activó. ¿Hay algún tiempo de espera involucrado? Estoy usando Zsh normalmente, pero también lo probé con bash como shell de inicio de sesión remoto.-o ServerAliveInterval=3 -o ServerAliveCountMax=2
permite detectarlo rápidamente, pero ¿hay algo para el lado del servidor?Creo que podría encontrar el PID del proceso que está ejecutando en el servidor y enviar una señal con otro
ssh
comando (como este:)ssh server "kill -2 PID"
.Utilizo este método para enviar señales de reconfiguración a aplicaciones que se ejecutan en una máquina diferente (mis aplicaciones capturan SIGUSR1 y leen un archivo de configuración). En mi caso, encontrar PID es fácil, porque tengo nombres de proceso únicos y puedo encontrar el PID enviando una
ps
solicitud a través dessh
.fuente
La solución evolucionó a http://www.gnu.org/software/parallel/parallel_design.html#Remote-Ctrl-C-and-standard-error-stderr
fuente
----- command.sh
----- en la terminal local
fuente