una - Cómo crear un túnel ssh en ruby y luego conectarse al servidor mysql en el host remoto
mysql ssh (5)
Me gustaría crear un script de ruby que pueda ejecutar comandos mysql en un servidor remoto a través de un túnel ssh.
Ahora mismo tengo un proceso manual para hacer esto:
- Crear un túnel -> ssh -L 3307: 127.0.0.1: 3306
- ejecutar el script de ruby.
- Cerrar túnel
Me encantaría poder automatizar esto para poder ejecutar el script.
ejemplo:
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
Una actualización - 2010-11-10:
Estoy muy cerca de este código:
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)
Cuando está durmiendo, puedo abrir una ventana de terminal y conectarme a mysql en el host remoto. Esto verifica que el túnel está creado y funcionando.
El problema ahora es cuando elimino las 3 líneas, simplemente se cuelga.
Esta podría ser una posible solución:
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)
Tal vez hay una mejor manera, pero esto funciona para lo que estaba tratando de hacer.
He estado probando el código de puerta de enlace anterior, una diferencia principal es que tengo que usar las claves ssh para acceder sin contraseña, pero también encontré el código que transmite la declaración Mysql.connect. Sin embargo, cuando reemplacé
mysql = Mysql.connect("127.0.0.1",...)
con
mysql = Mysql.connect("localhost",...)
funcionó bien
Mi código final se ve así:
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!
Por lo general, cuando un túnel está activo vinculando un puerto local al puerto de la aplicación remota, simplemente se conecta al puerto local como si fuera el remoto. Recuerde que MySQL tiene políticas de acceso basadas en la ubicación de origen de la conexión, por lo que es posible que desee tener esto en cuenta. En mi opinión, no hay session.forward.localessessary.
Por supuesto, todavía no hablas el protocolo de conexión MySQL así que esto podría no ser lo que deseas. Puede ser más fácil eliminar las consultas para ejecutar en un archivo, luego ejecutar mysql -u "usuario" -p "contraseña"
Pude hacer que esto funcionara sin un tenedor usando la gema 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
También puedes probar esta agradable gema de rubí: https://github.com/progrium/localtunnel