Подтвердить что ты не робот

Как создать туннель ssh в ruby, а затем подключиться к серверу mysql на удаленном хосте

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

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

  • Создать туннель → ssh -L 3307: 127.0.0.1: 3306
  • запустить ruby ​​ script.
  • Закрыть туннель.

Я хотел бы иметь возможность автоматизировать это, поэтому я могу просто запустить script.

Пример:

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

4b9b3361

Ответ 1

Мне удалось заставить это работать без вилки, используя камень 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

Ответ 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)  

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

Ответ 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!

Ответ 4

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

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