【问题标题】:How to create a ssh tunnel in ruby and then connect to mysql server on the remote host如何在 ruby​​ 中创建 ssh 隧道,然后连接到远程主机上的 mysql 服务器
【发布时间】:2011-05-05 11:10:34
【问题描述】:

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

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

  1. 创建隧道 -> ssh -L 3307:127.0.0.1:3306
  2. 运行 ruby​​ 脚本。
  3. 关闭隧道。

我希望能够自动执行此操作,以便我可以运行脚本。

示例:

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 行时,它就挂起。

【问题讨论】:

    标签: mysql ruby ssh


    【解决方案1】:

    我能够使用 mysql2 gem 在没有分叉的情况下让它工作

    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
    

    【讨论】:

    • 只要确保将 port = gateway.open('127.0.0.1', 3306, 3307) 更改为 port = gateway.open('myrdsinstance.whatever.com', 3306, 3307) 如果你正在使用 rds
    • 有没有其他人在尝试创建 Mysql2 客户端后被卡住了?我收到一个错误:Mysql2::Error: Lost connection to MySQL server at 'reading initial communication packet', system error: 0
    【解决方案2】:

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

    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)  
    

    也许有更好的方法,但这适用于我正在尝试做的事情。

    【讨论】:

    • 很奇怪,没有叉子就不行,我试过Redis和Mongo,没有任何叉子也能正常工作。一定是mysql驱动的问题。
    • 当我尝试时,我得到NameError: uninitialized constant Net::SSH::Service::Forward::UNIXServer。知道为什么吗?
    【解决方案3】:

    我一直在尝试上面的网关代码,一个主要区别是我必须使用 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!
    

    【讨论】:

    • 好吧,这并没有真正起作用 - 它只是连接到我本地机器上的 mysql。
    【解决方案4】:

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

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

    【讨论】:

    • TME,感谢您的回复。我知道访问控制设置正确,因为一切都以“手动”方式工作。
    【解决方案5】:

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

    【讨论】:

    猜你喜欢
    • 2014-05-03
    • 2020-06-05
    • 2016-02-13
    • 2016-08-04
    • 2016-11-18
    • 1970-01-01
    • 2015-04-23
    • 2016-04-17
    • 2020-09-30
    相关资源
    最近更新 更多