Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/ruby-on-rails/54.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Ruby on rails 使用Mysql数据库从Heroku到远程服务器的SSH_Ruby On Rails_Ruby On Rails 4_Heroku - Fatal编程技术网

Ruby on rails 使用Mysql数据库从Heroku到远程服务器的SSH

Ruby on rails 使用Mysql数据库从Heroku到远程服务器的SSH,ruby-on-rails,ruby-on-rails-4,heroku,Ruby On Rails,Ruby On Rails 4,Heroku,我正在研究一个需要建立远程SSH会话SSH隧道的Rails应用程序?作为后台ActiveRecord会话的一部分,从Heroku到远程Mysql数据库。我们的目标是在不同的时间通过这个渠道将数据迁移到应用程序中。通过web连接到远程mysql数据库将不是一个选项 几个问题: 希罗库允许他们关掉Dyno吗? 有什么问题 这样做的缺点是什么? 我会担心宋承宪吗 会话持久性作业可能需要1小时? 最后,我如何配置Rails和Heroku以启用远程连接 database.yml mysql端点? 好吧,我

我正在研究一个需要建立远程SSH会话SSH隧道的Rails应用程序?作为后台ActiveRecord会话的一部分,从Heroku到远程Mysql数据库。我们的目标是在不同的时间通过这个渠道将数据迁移到应用程序中。通过web连接到远程mysql数据库将不是一个选项

几个问题:

希罗库允许他们关掉Dyno吗? 有什么问题 这样做的缺点是什么? 我会担心宋承宪吗 会话持久性作业可能需要1小时? 最后,我如何配置Rails和Heroku以启用远程连接 database.yml mysql端点?
好吧,我现在可以回答我自己的问题了,经过几天的探索。简言之,是的

class LegacyAccount < ActiveRecord::Base

 self.table_name = "account"

 def self.test_connection

      # net-ssh-gateway gem
      gateway = Net::SSH::Gateway.new("ip_address","ssh_user_name",
          password: "password",
          port: "port if different from 22",
          verbose: :debug
          )

      port = gateway.open('127.0.0.1', 3306, 3307)

      establish_connection :legacy_production

      result = LegacyAccount.first
      puts "Record: #{result.to_yaml}"

      gateway.close(port)
      gateway.shutdown!

      result
  end

end

我尝试了@user1322092的方法,但当多个客户机试图访问数据库时遇到了麻烦,因为每个客户机都试图打开一个连接,但第一个客户机会出错

我创建了一个庞大的解决方案,包括在dyno上生成一个SSH进程,并将其用于所有通信。血淋淋的细节正在调查中。除了非常笨拙之外,无论您是否正在访问远程数据库,每次进程启动时都会导致延迟

使现代化 因此,这里有一种更好的方法似乎效果很好:只需捕获并忽略Errno::EADDRINUSE错误。代码如下:

require 'net/ssh/gateway'

class Mole

  TUNNEL_HOST = <redacted>
  TUNNEL_USER = <redacted>
  AWS_HOST = <redacted>
  TUNNEL_PORT_NUMBER = 3307

  attr_reader :tunnel_gateway, :tunnel_port

  # Call this to open an SSH tunnel from the current machine.  If the
  # the tunnel was already opened (e.g. by another process) , you'll
  # get a warning message
  def open_tunnel
    @tunnel_gateway = Net::SSH::Gateway.new(TUNNEL_HOST, TUNNEL_USER)
    begin
      @tunnel_port = @tunnel_gateway.open(AWS_HOST, 3306, TUNNEL_PORT_NUMBER)
    rescue Errno::EADDRINUSE => e
      $stderr.puts("Warning: #{e.class}: #{e.message}")
    end
  end

  # You won't normally call this, because the tunnel is a system wide
  # resource; you don't know when other processes want to release it.
  def close_tunnel
    r = @tunnel_gateway.close(@tunnel_port) if @tunnel_gateway
    @tunnel_gateway.shutdown!
    r
  end

end

只需补充一点,我愿意创建SSH隧道作为后台工作的一部分。不确定这是否会使迁移更容易。因为我正在迁移数据,所以过程是连续的;然而,我发现我的第一个SSH隧道连接是成功的,但是第二个会抛出“mysql连接已经消失”…grrrr。。所以我运行了heroku ps:restart,我想这会导致下一个连接成功。这就是你遇到的问题吗?@user1322092:我只是在本地机器上测试。我收到了一条不同的错误消息抱歉,我记不起确切的消息,但可能是相同的原因:试图重新打开一个已经打开的ssh隧道。我怀疑根本原因是隧道是每台机器的,如果您有单独的进程试图创建隧道,除了第一个进程之外,其他所有进程都会出错。也许有一种方法可以检测隧道是否已经在运行……我认为这种方法失败的地方是在网关中。打开调用-如果另一个进程已经打开了端口,您将得到一个错误,而且恐怕无法事先检测到。我开始认为正确的方法是在这种情况下简单地捕获并忽略EADDRINUSE异常。更多讨论请参见。@fearless_傻瓜,是的。。。这个解决方案测试并不是为了说明/支持多个流程,所以我添加了后台工作。在后台作业中,只有一个进程会打开网关。另外,在Heroku上测试成功,这是我最初的问题。我的应用程序也从后台任务访问远程数据库,区别在于我在不同的进程中有多个任务。我已经简单地测试了使用方法,它似乎很好地满足了我的需求。谢谢你帮我完成了80%的行程!
require 'net/ssh/gateway'

class Mole

  TUNNEL_HOST = <redacted>
  TUNNEL_USER = <redacted>
  AWS_HOST = <redacted>
  TUNNEL_PORT_NUMBER = 3307

  attr_reader :tunnel_gateway, :tunnel_port

  # Call this to open an SSH tunnel from the current machine.  If the
  # the tunnel was already opened (e.g. by another process) , you'll
  # get a warning message
  def open_tunnel
    @tunnel_gateway = Net::SSH::Gateway.new(TUNNEL_HOST, TUNNEL_USER)
    begin
      @tunnel_port = @tunnel_gateway.open(AWS_HOST, 3306, TUNNEL_PORT_NUMBER)
    rescue Errno::EADDRINUSE => e
      $stderr.puts("Warning: #{e.class}: #{e.message}")
    end
  end

  # You won't normally call this, because the tunnel is a system wide
  # resource; you don't know when other processes want to release it.
  def close_tunnel
    r = @tunnel_gateway.close(@tunnel_port) if @tunnel_gateway
    @tunnel_gateway.shutdown!
    r
  end

end