I use Net::SSHv2 to connect to a server and start a script on that server. So far it is working, but I want to interrupt the script when it is running for over 10 minutes or the output file gets too big. After receiving the interrupt the script will shutdown and output some statistics.
My current code looks like this:
File.open(filename, "w") do |f|
Net::SSH.start(host, user, password: password) do |ssh|
ssh.exec! "do_work" do |channel, stream, data|
f << "data"
#break if f.size > 1024 * 1024 * 100 #file size > 100 MB
#channel.send_data "^C" if f.size > 1024 * 1024 * 100 #file size > 100 MB
end
end
end
I tried a couple of other things with opening a block for the channel and requesting a shell, but it didn't work.
send_data
is the correct approach, but:
^
) followed by a capital C character to mean "send the character that is generated by a keyboard BIOS when you press CTRL+C". You have to send the ASCII character itself, which is the ETX
(end of text) control character and is represented in C hexadecimal escape sequence as \x03
.SIGINT
signal - its the terminal break signal which is unrelated to the POSIX signal IPC, but shells often interpret an ETX
as "the user wants me to send a SIGINT to the process" - which is the main reason why you need a PTY - it instructs the system shell to honor this "keyboard generated control characters should be converted to signals" convention. There is currently no way to send actual signals over the SSH session with common SSH implementations. See this answer to a similar (though not Ruby specific) question for more details.Your code should probably look like this:
File.open(filename, "w") do |f|
Net::SSH.start(host, user, password: password) do |ssh|
ssh.open_channel do |channel|
channel.request_pty
channel.exec "do_work" do |ch, success|
raise "could not execute command: #{command.inspect}" unless success
channel.on_data do |ch2, data|
f << data
end
#break if f.size > 1024 * 1024 * 100 #file size > 100 MB
channel.send_data "\x03" if f.size > 1024 * 1024 * 100 #file size > 100 MB
end
end.wait
end
end
The channel working code was copied more or less verbatim from session.rb source code. Please refer to that for more information.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With