如何在ruby中创建ssh隧道,然后连接到远程主机上的mysql服务器

时间:2010-11-05 05:36:46

标签: mysql ruby ssh

我想创建一个ruby脚本,我可以通过ssh隧道在远程服务器上运行mysql命令。

现在我有一个手动过程来执行此操作:

  1. 创建隧道 - > ssh -L 3307:127.0.0.1:3306
  2. 运行ruby脚本。
  3. 关闭隧道。
  4. 我希望能够自动执行此操作,以便我可以运行该脚本。

    示例:

    require 'rubygems'   
    require 'net/ssh/gateway'  
    require 'mysql'  
    
    
    #make the ssh connection -> I don't think I am doing this right.
    
    Net::SSH.start('server','user') do |session|
    
      session.forward.local(3307,'127.0.0.1', 3306)<br>
      mysql = Mysql.connect("127.0.0.1","root","","",3307)
    
      dbs = mysql.list_dbs<br>
      dbs.each do |db|<br>
        puts db <br>
      end
    
      session.loop(0){true}<br>
    end
    

    更新 - 2010-11-10:
    我真的很接近这个代码:

    require 'rubygems'  
    require 'mysql'  
    require 'net/ssh/gateway'  
    
    gateway = Net::SSH::Gateway.new("host","user",{:verbose => :debug})
    port = gateway.open("127.0.0.1",3306,3307)
    
    #  mysql = Mysql.connect("127.0.0.1","user","password","mysql",3307)  
    #  puts "here"  
    #  mysql.close  
    
    sleep(10)  
    gateway.close(port)
    

    当它休眠时,我能够打开终端窗口并连接到远程主机上的mysql。这将验证隧道是否已创建并正常工作。

    现在的问题是,当我取消注释3行时,它只是挂起。

5 个答案:

答案 0 :(得分:27)

我能够使用mysql2 gem

在没有fork的情况下使用它
require 'rubygems'
require 'mysql2'
require 'net/ssh/gateway'

gateway = Net::SSH::Gateway.new(
  'remotehost.com',
  'username'
 )
port = gateway.open('127.0.0.1', 3306, 3307)

client = Mysql2::Client.new(
  host: "127.0.0.1",
  username: 'dbuser',
  password: 'dbpass',
  database: 'dbname',
  port: port
)
results = client.query("SELECT * FROM projects")
results.each do |row|
  p row
end
client.close

答案 1 :(得分:6)

这可能是一种可能的解决方案:

require 'rubygems'  
require 'mysql'  
require 'net/ssh/gateway'  


gateway = Net::SSH::Gateway.new("server","user")  
port = gateway.open("127.0.0.1",3306,3307)

  child = fork do  
    mysql = Mysql.connect("127.0.0.1","user","password","mysql",port)  
    sql = "select sleep(5)"  
    mysql.query(sql)  
    mysql.close  
    exit  
  end  
  puts "child: #{child}"  
Process.wait  
gateway.close(port)  

也许有更好的方法,但这适用于我想要做的事情。

答案 2 :(得分:4)

我一直在尝试上面的网关代码,一个主要区别是我必须使用ssh密钥进行无密码访问,但也发现代码处理Mysql.connect语句。但是,当我更换

mysql = Mysql.connect("127.0.0.1",...)

mysql = Mysql.connect("localhost",...)

它运作良好。

我的最终代码如下:

require 'rubygems'
require 'mysql'
require 'net/ssh/gateway'

gateway = Net::SSH::Gateway.new('host',
           'user',
           :keys => ['myprivatekey.pem'],
           :verbose => :debug)
port = gateway.open("127.0.0.1",3306,3307)

mysql = Mysql.connect("localhost","dbuser","dbpassword","dbname",3307)
puts "here"
mysql.close

gateway.close(port)
gateway.shutdown!

答案 3 :(得分:0)

通常,当隧道将本地端口绑定到远程应用程序端口时,您只需连接到本地端口,就像它是远程端口一样。请记住,MySQL具有基于连接源位置的访问策略,因此您可能需要牢记这一点。在我看来,没有session.forward.local nessessary。

当然,你仍然不会说MySQL连接协议,所以这可能不是你想要的。删除任何要运行到文件中的查询可能更容易,然后运行mysql -u“user”-p“password”

答案 4 :(得分:-1)

你也可以尝试这个漂亮的红宝石宝石:https://github.com/progrium/localtunnel