Unless you have a PTY, you can't send control characters. This can be as easy as calling request_pty
.
It took me a while to figure out, mostly as my system is a bit more complicated - I have multiple SSH sessions running and another thread needs to cause all channels to terminate, so my code looks something like this:
def do_funny_things_to_server host,user
Net::SSH.start(host, user) do |ssh|
@connections << ssh
ssh.open_channel do |chan|
chan.on_data do |ch, data|
puts data
end
# get a PTY with no echo back, this is mostly to hide the "^C" that
# is otherwise output when I interrupt the channel
chan.request_pty(modes: [ [ Net::SSH::Connection::Term::ECHO, 0] ])
chan.exec "tail -f /some/log/file"
end
ssh.loop(0.1)
@connections.delete ssh
end
end
def cancel_all
@connections.each do |ssh|
ssh.channels.each do |id,chan|
chan.send_data "\x03"
end
end
end
###Rant:
There's so little documentation about how to use request_pty
parameters that it can be said to not exist. I had to figure out modes:
by reading both the source of net-ssh
and the SSH RFC and sprinkling some educated guesses about the meaning of the word "flags" in section 8 of the RFC.
Someone pointed in another relevant (though not Ruby specific) answer that there's a "signal"
message that can be used to send signals over the SSH connection, but also that OpenSSH (the implementation I use for the server) does not support it. If your server supports it, you might want to try to use it like this:
channel.send_channel_request 'signal', :string, 'INT'
See "signal"
channel message in the RFC and the buffer.rb
source file to understand the parameters. Insert here the expected rant about complete lack of documentation of how to use send_channel_request
. The above suggestion is mostly to document for myself how to use this method.
The answer linked above also mentions an SSH extension called "break"
which is supposedly supported by OpenSSH, but I couldn't get it to work to interrupt a session.