How to Get SSH to Forward Signals – Remote TTY Guide

remotesignalssshtty

I want to be able to send signals (SIGINT is the most important) through ssh.

This command:

ssh server "sleep 1000;echo f" > foo

will start sleep on server and after 1000 seconds it will put 'f\n' in the file foo on my local machine. If I press CTRL-C (i.e. send SIGINT to ssh) it will kill ssh, but it will not kill sleep on the remote server. I want it to kill sleep on the remote server.

So I tried:

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

But if stdin is not a terminal I get this error:

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

and then SIGINT is still not forwarded.

So I tried:

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

But then the output in foo is not 'f\n' but instead 'f\r\n' which is disastrous in my situation (as my output is binary data).

In the above I use "sleep 1000;echo f", but in reality that is supplied by the user, thus it can contain anything. However, if we can make it work for "sleep 1000;echo f" we can most likely make it work for all realistic situations.

I really do not care about getting a pseudo-terminal at the other end, but I have been unable to find any other way of getting ssh to forward my SIGINT.

Is there another way?

Edit:

The user could give commands that read binary data from stdin, such as:

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

The user could give commands that are cpu intensive, such as:

ssh server "timeout 1000 burnP6"

Edit2:

The version that seems to work for me is:

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

Thanks to digital_infinity for pointing me in the right direction.

Best Answer

Short answer:

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

and stop the program by CTRL+N.

Long explanation:

  1. You must use stty option intr to change your server or local interrupt character to not collide with each other. In the command above I've changed the server interrupt character to CTRL+N. You can change your local interrupt character and leave the server's one without any changes.
  2. If you don't want the interrupt character to be in your output (and any other control character) use stty -echoctl.
  3. You must assure that control characters are switched on on the server bash invoked by sshd . If you don't you can end up with processes still hanging around after you logout. stty isig
  4. You actually catch SIGINT signal by trap '/bin/true' SIGINT with empty statement. Without the trap you will not have any stdout after SIGINT signal on your end.
Related Question