【发布时间】:2023-03-22 06:04:01
【问题描述】:
很多文章都通过使用块来演示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 类中使用它,并从我的应用程序中的各种其他函数和方法调用它。例如,我有一个 SSHCommand 类,它执行以下操作:
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 连接从我的工作人员发送多个命令。
我没有按照预期的方式使用它,还是在我完成任务后有一种实际的方法可以关闭此连接?
【问题讨论】:
-
您也可以重写初始化程序以使用块,例如
SSHCommand.new { |ssh| ssh.execute("ifconfig") ... } -
有没有办法按照它写的方式关闭它?
-
好吧,你的
SSHCommand班级不知道工人何时完成发送命令,是吗?将工人的代码包装在一个块中是我能想到的最简单的方法。另一种方法是使用ObjectSpace.define_finalizer,但在我看来,一个普通的块要干净得多。 -
明白了。说得通。我很感激!
标签: ruby-on-rails ruby ssh net-ssh