Проблемы с подключением к MySQL через SSH
Я использую сайт узла Express на моей машине с OS X локально.
Мне нужно SSH к удаленной базе данных MySQL, чтобы я мог начать писать запросы к нему.
Теперь я могу подключиться к нашему удаленному серверу (работающему с базой данных mysql) в облаке, когда я делаю это через мой терминал OS X Yosemite.
Но я не добился успеха, пытаясь сделать это в коде, используя промежуточное программное обеспечение узла node-mysql и tunnel-ssh.
Мой код работает, но на самом деле не выдает ошибку, за исключением моего GET при отладке моего экспресс-приложения в Webstorm.
Некоторые факты:
Я могу SSH в MySQL из OS X с помощью этой команды:
ssh -L 3306: 127.0.0.1: 3306 ourCloudServerName.net MyUserNameHere
Я могу подключиться к MySQL с помощью следующей команды:
mysql -h localhost -p -u myUserNameHere
Когда я в командной строке mysql и типа SHOW GLOBAL VARIABLES LIKE 'PORT', я получаю, что сервер (или база данных, я думаю, это означает... не уверен) работает на порт 3306
Я отлаживаю с помощью Webstorm 10.0.3 Это означает, что я отлаживаю свое приложение Node Express, которое запускается так:
var port = 3000;
app.set ("порт", порт);
app.listen (app.get ('port'), function () {console.log ('Экспресс-веб-сервер прослушивает порт' + app.get('port')); })
- Я могу запустить свое экспресс-приложение через localhost:3000 в Chrome
Теперь вот моя первая попытка попробовать использовать оба узла-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;
};
router /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. Соединения показывают 0 в объекте сервера ssh во время отладки
2) MySQL объект подключения показывает отключен, никогда не подключен
3) Я также получаю эту ошибку узла в Webstorm во время работы экспресс-сайта, который не сообщает мне:
В каком соединении отказано, я запускаю этот сайт через локальный порт 3000. Это говорит о том, что он не может подключиться к ssh? Я понятия не имею, здесь. Это не всегда проявляется или происходит, это периодически возникающая ошибка, и она может быть просто отладкой веб-шторма, когда мне просто нужно снова запустить отладку и обычно она исчезает... но может быть взаимосвязана, без понятия.
И вот что имеет мой объект конфигурации, когда я проверяю его во время отладки
И в tunnel-ssh / index.js, строка 70, где он возвращает сервер, который пытается создать, я вижу, что ssh-соединения нет:
ОБНОВЛЕНИЕ - согласно предложениям от ответов
2 ответа
Это на самом деле может быть упрощено, если все, что вам нужно сделать, это туннелировать соединения MySQL из вашего приложения. mysql2
Модуль (лучше) поддерживает передачу пользовательского потока для использования в качестве соединения с базой данных, это означает, что вам не нужно запускать локальный TCP-сервер и прослушивать соединения для туннелирования.
Вот пример использования mysql2
а также ssh2
:
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 остановлены, например). Как правило, вы можете просто добавить error
обработчики событий для ssh
а также db
обрабатывать большинство случаев, хотя вы можете слушать end
события, чтобы знать, когда вам нужно восстановить либо ssh
а также db
соединения.
Кроме того, может быть целесообразно настроить keepalive как на уровне ssh, так и на уровне mysql. ssh2
имеет несколько опций keepalive, которые ведут себя так же, как опцию keepalive клиента OpenSSH. За mysql2
Обычно я просто звоню db.ping()
на некотором интервале. Вы можете передать обратный вызов, который будет вызван, когда сервер ответит на эхо-запрос, так что вы можете использовать дополнительный таймер, который очищается при выполнении обратного вызова. Таким образом, если обратный вызов не выполняется, вы можете попытаться восстановить соединение.
Это проблема SELinux, и вашему httpd / webserver не разрешено подключаться по сети, ответьте на вашу проблему следующей командой:
setsebool -P httpd_can_network_connect 1
Это должно работать нормально тогда. Я полагаю, вы используете Apache?