如何正确关闭 Net::SSH 连接?

How to properly close a Net::SSH connection?

很多文章都用块来演示Net::SSH,比如下面的:

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

但是,我实际上是在 Ruby class 中使用它,并从我的应用程序中的各种其他函数和方法调用它。例如,我有一个 SSHCommand class 执行以下操作:

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

要通过 SSH 连接执行命令,我只需 运行 以下内容:

ssh = SSHCommand.new
ssh.execute("ifconfig")

如何真正终止此 SSH 会话?我注意到当我在 Ruby on Rails 的 Sidekiq 工作人员完成时,我收到以下消息:

zlib(finalizer): the stream was freed prematurely.
zlib(finalizer): the stream was freed prematurely.

我避免使用块的原因是因为我希望通过已建立的 SSH 连接从我的工作人员发送多个命令来执行。

我是否没有按照预期的方式使用它,或者在我完成任务后是否有关闭此连接的实际方法?

如果您在没有阻止的情况下启动 SSH 连接,您将得到一个 Net::SSH::Connection::Session,您最终应该在其上调用 close

这里有一个 Net::SSH demonstration program,加上一些图像和指向 Net::SSH 整体工作原理的交互式可视化链接,包括 close