我正在寻找一个Rails应用程序,它需要从Heroku到远程Mysql数据库建立一个远程SSH会话(SSH隧道?),作为后台ActiveRecord会话的一部分。目标是通过此渠道在不同时间将数据迁移到应用程序中。通过Web连接到远程mysql数据库不是一个选项。
几个问题:
答案 0 :(得分:0)
好吧,我现在能够在挖掘了几天之后回答我自己的问题。简而言之,是的。
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
并在您的database.yml中:
legacy_production:
adapter: "mysql2"
host: "127.0.0.1"
username: "root"
password: "password"
database: "legacydb"
port: 3307
secure_auth: false
答案 1 :(得分:0)
我试过@ user1322092的方法,当多个客户端试图访问数据库时遇到了麻烦,因为每个客户端都会尝试打开一个连接(除了第一个连接都会出错)。
我创建了一个可怕的解决方案,涉及在dyno上生成SSH进程并将其用于所有通信。血腥细节在https://stackoverflow.com/a/27361295/558639。除了真正的kludgy之外,每次进程启动时都会导致延迟,无论您是否正在访问远程数据库。
因此,这是一种似乎运行良好的更好的方法:只是陷阱(和忽略)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