在 ruby 中创建后台 ssh 隧道

create a background ssh tunnel in ruby

我的 oracle 数据库只能通过跳转服务器访问并且是负载平衡的。结果,我 运行 在 bash 中使用了以下后台隧道命令:

ssh ${jumpoffUser}@${jumpoffIp} -L1521:ont-db01-vip:1521 -L1522:ont-db02-vip:1521 -fN

在我 运行 之前,我使用 sqlplus 在数据库上的命令如下:

sqlplus #{@sqlUsername}/#{@sqlPassword}@'#{@sqlUrl}' @scripts/populateASDB.sql

一切正常。

现在我想对这个程序进行 rubisize。

在查找有关 ruby 的文档时,我找不到如何将隧道置于后台(这是我的偏好),但我找到了有关本地端口转发的文档,我认为它可以模拟上述内容隧道和随后的 sqlplus 命令。

这是我的代码:

Net::SSH.start( @jumpoffIp, @jumpoffUser ) do |session|
  session.forward.local( 1521, 'ont-db01-vip', 1521 )
  session.forward.local( 1522, 'ont-db02-vip', 1521 )
  puts "About to populateDB"
  res = %x[sqlplus #{@sqlUsername}/#{@sqlPassword}@'#{@sqlUrl}' @scripts/populateASDB.sql > output.txt]
  puts "populateDb output #{res}"
  session.loop
end

当我 运行 以上时,我得到行 "About to populateDB" 但它挂在 sqlplus 命令的实际 运行ning 上。我的端口转发代码有问题吗?或者我该如何输入以下内容:

ssh ${jumpoffUser}@${jumpoffIp} -L1521:ont-db01-vip:1521 -L1522:ont-db02-vip:1521 -fN

变成ruby代码?

一个

尝试使用这个 gem:https://github.com/net-ssh/net-ssh-gateway/

require 'net/ssh/gateway'

gateway = Net::SSH::Gateway.new(@jumpoffIp, @jumpoffUser)
gateway.open('ont-db01-vip', 1521, 1521)
gateway.open('ont-db02-vip', 1521, 1521)

res = %x[sqlplus #{@sqlUsername}/#{@sqlPassword}@'#{@sqlUrl}' @scripts/populateASDB.sql > output.txt]
puts "populateDb output #{res}"

gateway.shutdown!

你有两个问题。

1) 您需要使用 'session.loop { true }' 以便会话实际循环

2) 在 sqlplus 命令完成之前,您不会开始循环会话,但是 sqlplus 需要会话循环(转发启动)。

所以我建议使用 Thread.new 创建一个后台线程,然后在 sqlplus 完成后终止线程。

感谢 David 的回答,我得出以下结论:

Net::SSH.start(ip_addr, 'user') do |session|
session.forward.local( 9090, 'localhost', 9090 )
  # Need to run the event loop in the background for SSH callbacks to work
  t = Thread.new {
    session.loop { true }
  }
  commands.each  do | command |
    command.call(9090)
  end

  Thread.kill(t)
end