头图

利用ssh正向代理和mongodump实现远程定时备份mongodb数据库

wkArtist

最近在使用nodejs,express,mongodb做一些后端项目,数据量不是很大,最开始在数据库备份这一块选择在主目录创建一个dump文件夹,程序启动时开启一个定时任务,每天凌晨1点mongodump一下当前的数据库。但总担心当前服务器硬盘坏了怎么办,我的数据不就没了?所以有了一个想法:在另一台服务器上也去定时备份我的项目服务器上的数据库。mongodump本身有着强大的功能,可以远程备份数据库:

mongodump -h 远端IP地址 -u 登录用户 -p 登录密码 -d 数据库名 --port 远端mongod端口(默认27017) -o 输出到本机的路径

但是现在企业中服务器都是通过ssh去登录访问的,mongodump提供了用户名密码的方式但没有提供使用ssh访问的功能配置,所以这是我要解决的问题。

我们知道ssh命令除了登陆外还有三种代理功能:正向代理(-L)、反向代理(-R)、socks5 代理(-D),在这里我们可以使用正向代理来代理到我们本机的某个端口,然后再mongodump本机不就完成我的目的了吗?

ssh -L :本机代理端口:localhost:远程mongod进程端口 远程登录用户名@远程服务器地址

这里的本机指的也是一个服务器,因为我要写一个专门用来备份的nodejs应用,并部署到一个备份服务器上。

项目目录如下:

├─dump //数据库存放目录
├─app.js //服务器启动
├─config.js //配置文件
├─cronFunc.js //定时任务
├─init.js //初始化功能
├─mongodump.js //备份数据库
├─sslProxy.js //ssh正向代理
├─util.js //工具函数
├─package.json
├─README.md
├─server.json

项目中一共使用了3个包:

"dependencies": {
    "express": "^4.17.1", //启动服务
    "node-cmd": "^4.0.0", //调用系统终端执行命令
    "node-cron": "^2.0.3" //开启定时任务
  }
  • 配置文件
// config.js
module.exports = {
    APP_PORT: 7003, //本应用的端口

    DUMPPROXY_PORT: 9876, //mongo本机代理端口
    REMOTE_MONGOD_PORT: 27017, //数据库所在的服务器mongod服务端口
    REMOTE_HOST: '*.*.*.*',//数据库所在的服务器地址
    REMOTE_PORT: 22, //数据库所在的服务器ssh登录端口
    REMOTE_USER: 'root', //数据库所在的服务器登录用户名
    REMOTE_DB_NAME: 'my-db', //所需备份的数据库名

    CRON_RULE: '0 0 0/6 * * ?', //指定cron规则,按此规则进行定时备份
}

核心代码主要包括两处:

  • ssh正向代理
// sslProxy.js
const cmd = require('node-cmd');
const {DUMPPROXY_PORT,REMOTE_MONGOD_PORT,REMOTE_HOST,REMOTE_PORT,REMOTE_USER} = require('./config')
let fun = {}
fun.startProxy = async function () {
    try{
        const line = `ssh -L :${DUMPPROXY_PORT}:localhost:${REMOTE_MONGOD_PORT} ${REMOTE_USER}@${REMOTE_HOST} -p ${REMOTE_PORT}`;
        console.log('开始ssh正向代理'+line)
        cmd.get(line, (err, data) => {
            if (!err){
                console.log('代理成功--------------------------')
            }else {
                throw new Error('代理失败')
            }
        })
    } catch(error) {
        console.log('代理失败++++++++++++++++++++++++++~~~~+'+error.msg)
    }
}
module.exports = fun

在这里我没有像mongodump.js中使用promise化后的cmd.get方法,是因为程序启动后先运行startProxy,在这里await时会持续阻塞,导致定时任务无法运行,使用异步的方式就不会影响。

  • 备份服务器
// mongodump.js
const DUMP_DIR = path.join(__dirname, './dump'); // 数据库备份地址

/**
 * @param {*} dirname 目录名称
 * @param {*} dbname 对应数据库名
 */
async function backup(dirname, dbname) {
    try {
        // 判断问卷夹
        const saveDir = `${DUMP_DIR}${path.sep}${dirname}`;
        if (!fs.existsSync(DUMP_DIR)) {
            fs.mkdirSync(DUMP_DIR);
        }
        if (!fs.existsSync(saveDir)) {
            fs.mkdirSync(saveDir);
        }

        const line = `mongodump --port ${DUMPPROXY_PORT} -d ${dbname} -o ${saveDir}`;
        console.log('执行命令:'+line)
        // 进行备份
        await cmdPromise(line);

        return dbname+'数据库备份完成'+dirname;

    } catch (error) {
        return `备份失败-${error.message}`;
    }
};

在每次备份时,我只是非常简单的使用时间戳作为路径名,备份数据数据库名和数据库名称一致。
项目跑起来后可以先把定时器间隔调短测试一下CRON_RULE: '*/60 * * * * ?',
我在linux(unbuntu16)上启动是没问题的,功能也都正常,备份文件以时间戳未路径名整齐排列:
image.png
打开某一个,可以看到标准的bson数据库文件,可以使用mongorestore进行恢复。
image.png

但我在windows上启动会报这个错误导致功能无法实现,虽说不会在windows上使用,但还是想知道原因,希望知道的小伙伴在评论区能告诉一下我!
image.png

附上github项目地址:https://github.com/WkArtist/m...

阅读 783
6 声望
3 粉丝
0 条评论
你知道吗?

6 声望
3 粉丝
文章目录
宣传栏