【问题标题】:Trouble Connecting to MySQL via SSH无法通过 SSH 连接到 MySQL
【发布时间】:2015-06-05 22:45:36
【问题描述】:

我在我的 OS X 机器上本地运行一个 node Express 网站。

我需要通过 ssh 连接到远程 mysql 数据库,以便开始编写查询。

现在我可以通过我的 OS X Yosemite 终端 ssh 到云端的远程服务器(运行 mysql 数据库)。

但我没有成功尝试在代码中使用 node-mysql 和 tunnel-ssh 节点中间件。

在 Webstorm 中调试我的 express 应用程序时,我的代码运行但除了我的 GET 之外并没有真正出错。

一些事实

  • 我可以使用以下命令从 OS X SSH 进入 mySQL:

    ssh -L 3306:127.0.0.1:3306 ourCloudServerName.net MyUserNameHere

  • 然后我可以使用以下命令连接到 mySQL:

    mysql -h localhost -p -u myUserNameHere

  • 1234563 p>
  • 我正在通过 Webstorm 10.0.3 进行调试 这意味着我正在调试我的 Node Express 应用程序,它的开头是这样的:

    var 端口 = 3000;

    app.set('port', 端口);

    app.listen(app.get('port'), function(){ console.log('Express Web 服务器正在监听端口' + app.get('port')); })

    • 我可以在 Chrome 中通过 localhost:3000 运行我的 express 应用

现在这是我第一次尝试同时使用 node-mysql 和 tunnel-ssh

mysqlConfig.js

var databaseConfig = module.exports = function(){};

 module.exports = {

    mySQLConfig: {
       host: '127.0.0.1',
       username: 'root',
       password: 'rootPassword',
       database: 'SomeDatabaseName',
       port: 3306,
       timeout: 100000
    },

    sshTunnelConfig: {
       username: 'myusername',
       password: 'mypassword',
       host: 'ourCloudServerName\.net',
       port: 22,
       //localPort: 3306, //4370
       //port: 3333,
       //localPort: 4370,
       dstPort: 3306,
       srcHost: 'localhost',
       dstHost: 'localhost',
       localHost: 'localhost'
    }
 };

connection.js

 var mysql = require('mysql'),
    config = require('./mysqlConfig'),
    tunnel = require('tunnel-ssh');


var connection = module.exports = function(){};

createDBConnection = function(){
    var mysqlConnection = mysql.createConnection({
        host: config.mySQLConfig.host,
        user: config.mySQLConfig.username,
        password: config.mySQLConfig.password,
        database: config.mySQLConfig.database,
        connectTimeout: config.mySQLConfig.timeout
    });

    return mysqlConnection;
};


connection.invokeQuery = function(sqlQuery){

    var data = undefined;

    var sshTunnel = tunnel(config.sshTunnelConfig, function(error, result) {

        var sqlConnection = createDBConnection();

        sqlConnection.connect(function (err) {
            console.log(err.code);
        });
        sqlConnection.on('error', function (err) {
            console.log(err.code);
        });

        data = sqlConnection.query({
            sql: sqlQuery,
            timeout: config.mySQLConfig.timeout
        }, function (err, rows) {

            if (err && err.code) {
                console.log("error code: " + err.code)
            }
            if (err) {
                console.error("error stack: " + err.stack)
            }
            ;

            if (rows) {
                console.log("We have Rows!!!!!!")
            }
        });

        sqlConnection.destroy();
    });

    return data;
};

路由器/index.js

var connection = require('../config/database/connection');
var express = require('express');
var router = express.Router();

router.get('/', function(req, res) {
    var sqlStatement = "Select top 10 from someTable";

    var rows = connection.invokeQuery(sqlStatement);
});

module.exports = router;

所以我尝试在 Webstorm 中进行调试,但我要么从来没有真正得到一个好的错误打印到控制台,要么如果我这样做了,这是一个通用的节点错误。我可能有一个基本的代码问题和/或只是没有正确设置值或没有正确使用中间件,我只是不知道,在调试期间它并没有告诉我太多。我只知道:

1) 我没有通过 ssh 连接到服务器。调试期间连接在 ssh 服务器对象中显示为 0

2) mysql连接对象显示断开,从未连接

3) 我在 Webstorm 中也遇到了这个节点错误,同时运行 express 网站并没有告诉我 jack:

什么连接被拒绝,我正在通过 localhost 端口 3000 运行这个网站。这是说它无法连接到 ssh 吗?我不知道这里。这并不总是出现或发生,它是一个间歇性错误,可能只是一个 webstorm 调试问题,我只需要再次运行调试并且通常会消失......但可能是相互关联的,没有线索。

这就是我在调试期间检查配置对象时的内容

在 tunnel-ssh/index.js 的第 70 行,它返回它尝试创建的服务器,我看到没有 ssh 连接:

更新 - 根据答案的建议

【问题讨论】:

  • 你能在 SSH 隧道回调中尝试 console.log(error, result) 看看 SSH 错误是什么吗?
  • 在我关闭数据库连接(破坏线)后我应该把它放在哪里?
  • 就在回调的开头(在 var sshTunnel... 之后)。如果你的帖子说的是真的,那么永远不会建立 SSH 连接,所以我们需要看看是什么原因造成的。
  • 我还需要确认我的配置值是否正确。我想我做对了……但谁知道呢……我是根据我在终端中通过 ssh 连接的方式来确定的,但我不确定我是否将正确的值连接到 dstPort、dstHost 等,或者是否我什至需要我设置 TBH 的所有变量。我无法确认 ssh 连接调用是否到达那里或由于 Ubuntu / mySQL 拒绝的无效配置值而失败,或者什么所以我瞎了。
  • 不知道你能不能用127.0.0.1代替localhost;我知道它们应该是相同的,但它消除了另一个潜在问题。

标签: javascript node.js ubuntu ssh node-mysql


【解决方案1】:

如果您需要做的只是从应用程序内部建立 MySQL 连接,这实际上可以简化。 mysql2 模块(更好地)支持传递自定义流以用作数据库连接,这意味着您不必启动本地 TCP 服务器并监听连接以通过隧道。

这是一个使用mysql2ssh2 的示例:

var mysql2 = require('mysql2');
var SSH2Client = require('ssh2').Client;

var sshConf = {
  host: 'ourCloudServerName.net',
  port: 22,
  username: 'myusername',
  password: 'mypassword',
};
var sqlConf = {
  user: 'root',
  password: 'rootPassword',
  database: 'SomeDatabaseName',
  timeout: 100000
};

var ssh = new SSH2Client();
ssh.on('ready', function() {
  ssh.forwardOut(
    // source IP the connection would have came from. this can be anything since we
    // are connecting in-process
    '127.0.0.1',
    // source port. again this can be randomized and technically should be unique
    24000,
    // destination IP on the remote server
    '127.0.0.1',
    // destination port at the destination IP
    3306,
    function(err, stream) {
      // you will probably want to handle this better,
      // in case the tunnel couldn't be created due to server restrictions
      if (err) throw err;

      // if you use `sqlConf` elsewhere, be aware that the following will
      // mutate that object by adding the stream object for simplification purposes
      sqlConf.stream = stream;
      var db = mysql2.createConnection(sqlConf);

      // now use `db` to make your queries
    }
  );
});
ssh.connect(sshConf);

当然,您将希望扩展此示例,在 ssh 和 mysql 级别添加错误处理,以防由于某种原因(例如 TCP 连接被切断或 ssh/mysql 服务停止)而消失。通常,您只需为sshdb 添加error 事件处理程序即可处理大多数情况,尽管您可能也想监听end 事件以了解何时需要重新建立@987654332 中的一个/两个@ 和 db 连接。

此外,在 ssh 和 mysql 级别配置 keepalive 可能是明智的。 ssh2 有几个 keepalive options 的行为就像 OpenSSH 客户端的 keepalive 选项一样。 对于mysql2,通常我所做的只是每隔一段时间调用db.ping()。您可以传入一个回调,该回调将在服务器响应 ping 时被调用,因此您可以使用一个额外的计时器,该计时器在回调执行时被清除。这样如果回调没有执行,你可以尝试重新连接。

【讨论】:

  • 谢谢让我试试。我想知道 connect-ssh 有什么意义
  • 甜蜜!看来我有一个 ssh 连接。现在刚刚得到 mysql auth 错误,正在处理它,希望很快就会工作。我什至没有看到mysql2,wtf!一开始就应该用这个!
  • 我想这只是尝试不同的mysql中间件的问题。谢谢
  • 感谢您的帮助。
  • @mscdex 但是这不适用于与 MySQL 的 SSL 连接。你知道问题可能是什么吗?我使用的主机不是本地主机。这会给我一个 SSL 连接超时错误,但是当我使用 putty 连接时它可以工作。
【解决方案2】:

这是 SELinux 问题,您的 httpd / webserver 不允许通过网络连接,您的问题的答案是以下命令:

setsebool -P httpd_can_network_connect 1

那么它应该可以正常工作。我相信您使用的是 apache?

【讨论】:

  • 我试图将它粘贴到终端(在我的本地 OS X 机器上),但它无法识别 setsebool
  • 这个命令不应该被复制到 SSH 终端 - 换句话说就是你试图连接的服务器吗?
  • 如果要从 Ubuntu 运行,我无法访问服务器,也不知道如果我能够从我的 OS X SSH 运行,为什么我需要运行它,但不能在节点中
  • @pbwned 在 SSH 终端中复制是什么意思。
  • 据我了解,您已将 maqsimum 给您的命令复制到您的 OS X 终端,对吗?但是您正在另一台服务器(称为 ourCloudServerName)上运行 SSH。复制那里的代码..
猜你喜欢
  • 2021-08-07
  • 2020-05-12
  • 2021-08-28
  • 2020-07-27
  • 2015-10-21
  • 1970-01-01
  • 1970-01-01
  • 2021-11-01
相关资源
最近更新 更多