Как создать туннель SSH в ruby, а затем подключиться к серверу MySQL на удаленном хосте - PullRequest
27 голосов
/ 05 ноября 2010

Я хотел бы создать скрипт ruby, который бы мог запускать команды mysql на удаленном сервере через туннель ssh.

Сейчас у меня есть ручной процесс, чтобы сделать это:

  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 строки, он просто зависает.

Ответы [ 5 ]

27 голосов
/ 28 марта 2012

Мне удалось заставить это работать без форка, используя gem mysql2

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
6 голосов
/ 11 ноября 2010

Это может быть одним из возможных решений:

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)  

Может быть, есть лучший способ, но это работает для того, что я пытался сделать.

4 голосов
/ 19 октября 2011

Я пробовал код шлюза, описанный выше, одно из основных отличий в том, что я должен использовать 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!
0 голосов
/ 04 января 2013

Вы также можете попробовать этот красивый рубиновый камень: https://github.com/progrium/localtunnel

0 голосов
/ 05 ноября 2010

Обычно, когда туннель работает, привязывая локальный порт к удаленному порту приложения, вы просто подключаетесь к локальному порту, как если бы он был удаленным.Помните, что MySQL имеет политики доступа, основанные на исходном расположении соединения, поэтому вы можете иметь это в виду.На мой взгляд, нет необходимого session.forward.local.

Конечно, вы все еще не говорите по протоколу соединения MySQL, так что это может быть не то, что вам нужно.Может быть проще отбросить любые запросы для запуска в файл, а затем запустить mysql -u "user" -p "password"

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...