Obtenez ssh pour transmettre les signaux

Je veux pouvoir envoyer des signaux (SIGINT est le plus important) via ssh.

Cette command:

ssh server "sleep 1000;echo f" > foo 

va commencer à dormir sur le server et après 1000 secondes, il mettra "f \ n" dans le file foo sur ma machine locale. Si j'appuie sur CTRL-C (c.-à-d. Envoyer SIGINT à ssh), il va tuer ssh, mais il ne va pas tuer le sumil sur le server distant. Je veux qu'il tue le sumil sur le server distant.

Alors j'ai essayé:

 ssh server -t "sleep 1000;echo f" > foo 

Mais si stdin n'est pas un terminal, j'obtiens cette erreur:

 Pseudo-terminal will not be allocated because stdin is not a terminal. 

et puis SIGINT n'est toujours pas transmis.

Alors j'ai essayé:

 ssh server -t -t "sleep 1000;echo f" > output 

Mais alors la sortie dans foo n'est pas 'f \ n' mais plutôt 'f \ r \ n' ce qui est désastreux dans ma situation (car ma sortie est des données binarys).

Dans ce qui précède, j'utilise "sleep 1000, echo f", mais en réalité fourni par l'user, il peut donc contenir n'importe quoi. Cependant, si nous pouvons le faire fonctionner pour «dormir 1000, écho f», nous pouvons très probablement le faire fonctionner pour toutes les situations réalists.

Je ne me soucie vraiment pas d'get un pseudo-terminal à l'autre bout, mais je n'ai pas pu find d'autre moyen d'envoyer ssh pour transmettre mon SIGINT.

Y a-t-il un autre moyen?

Modifier:

L'user pourrait donner des commands qui lisent datatables binarys de stdin, telles que:

 seq 1000 | gzip | ssh server "zcat|bzip2; sleep 1000" | bzcat > foo 

L'user pourrait donner des commands intensives en processeur, telles que:

 ssh server "timeout 1000 burnP6" 

Edit2:

La version qui semble fonctionner pour moi est:

 your_preprocessing | uuencode a | ssh -tt -oLogLevel=quiet server "stty isig -echoctl -echo ; uudecode -o - | your_command | uuencode a" | uudecode -o - | your_postprocessing 

Merci à digital_infinity pour m'avoir orienté dans la bonne direction.

Réponse courte:

 ssh -t fs "stty isig intr ^N -echoctl ; trap '/bin/true' SIGINT; sleep 1000; echo f" > foo 

et arrêtez le programme par CTRL + N.

Longue explication:

  1. Vous devez utiliser stty option intr pour changer votre server ou le caractère d'interruption local afin de ne pas entrer en collision les uns avec les autres. Dans la command ci-dessus, j'ai changé le caractère d'interruption du server en CTRL + N. Vous pouvez changer votre caractère d'interruption local et quitter celui du server sans aucun changement.
  2. Si vous ne souhaitez pas que le caractère d'interruption soit dans votre sortie (et tout autre caractère de contrôle), utilisez stty -echoctl .
  3. Vous devez vous assurer que les caractères de contrôle sont activés sur le server bash invoqué par sshd. Si vous ne le faites pas, vous pouvez vous refind avec des process qui traînent encore après votre déconnection. stty isig
  4. Vous attrapez réellement le signal SIGINT par le trap '/bin/true' SIGINT avec l'instruction vide. Sans le piège, vous n'aurez pas de stdout après le signal SIGINT de votre côté.

J'ai essayé toutes les solutions et c'était le meilleur:

 ssh host "sleep 99 < <(cat; kill -INT 0)" <&1 

https://stackoverflow.com/questions/3235180/starting-a-process-over-ssh-using-bash-and-then-killing-it-on-sigint/25882610#25882610

Je pense que vous pouvez find PID du process que vous utilisez sur le server et envoyer un signal en utilisant une autre command ssh (comme ceci: le ssh server "kill -2 PID" ).

J'utilise cette méthode pour envoyer des signaux de reconfiguration à des applications s'exécutant sur une machine différente (mes applications capturent SIGUSR1 et lisent un file de configuration). Dans mon cas, find un PID est facile, car j'ai des noms de process uniques et je peux find le PID en envoyant une requête ps via ssh .

La solution a évolué vers http://www.gnu.org/software/parallel/parallel_design.html#Remote-Ctrl-C-and-standard-error-stderr

 $SIG{CHLD} = sub { $done = 1; }; $pid = fork; unless($pid) { # Make own process group to be able to kill HUP it later setpgrp; exec $ENV{SHELL}, "-c", ($bashfunc."@ARGV"); die "exec: $!\n"; } do { # Parent is not init (ppid=1), so sshd is alive # Exponential sleep up to 1 sec $s = $s < 1 ? 0.001 + $s * 1.03 : $s; select(undef, undef, undef, $s); } until ($done || getppid == 1); # Kill HUP the process group if job not done kill(SIGHUP, -${pid}) unless $done; wait; exit ($?&127 ? 128+($?&127) : 1+$?>>8) 

—– command.sh

 #! /bin/sh trap 'trap - EXIT; kill 0; exit' EXIT (sleep 1000;echo f) & read ans 

—– sur le terminal local

 sleep 864000 | ssh -T server command.sh > foo