Many articles demonstrate Net::SSH
by using a block, such as the following:
Net::SSH.start("host", "user") do |ssh|
ssh.exec! "cp /some/file /another/location"
hostname = ssh.exec!("hostname")
ssh.open_channel do |ch|
ch.exec "sudo -p 'sudo password: ' ls" do |ch, success|
abort "could not execute sudo ls" unless success
ch.on_data do |ch, data|
print data
if data =~ /sudo password: /
ch.send_data("password\n")
end
end
end
end
ssh.loop
end
However, I am actually using it in a Ruby class and calling it from various other functions and methods within my application. For example, I have an SSHCommand
class that does the following:
class SSHCommand
def initialize
...
@ssh = establish_ssh
...
end
def establish_ssh
ssh = Net::SSH.start(
@ip, 'root',
:host_key => 'ssh-rsa',
:encryption => 'aes256-ctr',
:keys => [@key],
:compression => "zlib@openssh.com",
:port => @port
)
return ssh
end
def execute(command)
results = String.new
results = run_cmd(command)
if results.include? "no matches found"
results = ""
end
return results
end
end
and to execute a command over an SSH connection, I just simply run the following:
ssh = SSHCommand.new
ssh.execute("ifconfig")
How do I actually terminate this SSH session? I noticed that when my Sidekiq workers in Ruby on Rails are completed, I get the following message:
zlib(finalizer): the stream was freed prematurely.
zlib(finalizer): the stream was freed prematurely.
The reason I avoided using a block is because I wanted to have multiple commands sent from my worker to be executed via an already-established SSH connection.
Am I not using this the way it's intended, or is there an actual way to close this connection when I've completed my tasks?
If you start an SSH connection without a block, you'll get a Net::SSH::Connection::Session
, on which you should eventually call close.
Here is a Net::SSH demonstration program, plus some images and links to interactive visualizations of how Net::SSH works overall, including close
.