通过 ssh 同步 MongoDB

Posted

技术标签:

【中文标题】通过 ssh 同步 MongoDB【英文标题】:Sync MongoDB Via ssh 【发布时间】:2013-05-13 05:52:38 【问题描述】:

mysql 不同,我发现尝试同步 MongoDB 文件非常具有挑战性 - 它们不能通过管道返回,因为它们不会将数据发送到标准输出 (如果我理解正确的话)。

所以,我正在尝试另一种方法,它不涉及两次 ssh 调用。 需要做的是这样的:

登录 ssh 服务器 导出所有 MongoDB 文件 将它们压缩为 gzip 将它们发送回本地计算机 提取和导入

不过,这里的关键是不留下任何痕迹 - 我不希望压缩文件留在远程机器中, 这通常需要我进行另一个 ssh 登录。 因此,类似于“将文件移入存档”的方式是理想的解决方案, 如果以后可以无缝地通过管道传回本地机器。

我意识到 MongoDB 有一种使用 mongodump 连接到服务器凭据的方法,但是端口是关闭的 atm,所以我需要 SSH 方法。 欢迎任何其他想法,顺便说一句。

编辑 - 11.06.14

由于这个问题似乎有点受欢迎,我愿意分享一个脚本,该脚本是在去年从这个问题的答案和其他资源演变而来的(功劳是应得的)。 该脚本基本上管理从/到远程服务器的同步,可能适用于任何一种类型的数据库(暂时可能是 postgres、mysql 和 mongo)。 它确实有一些假设,比如 root 用户没有 db 的密码,但可以根据需要更改。

脚本可以在这里找到:https://github.com/iwfmp/zsh/blob/master/scripts/db/db-sync

【问题讨论】:

您是否有充分的理由不想要第二个ssh 电话?您还可以有一个cronjob,它会定期从远程服务器中删除档案。或者将上述所有步骤打包到一个脚本中,该脚本在内部执行 3 个ssh 调用(一个用于转储+存档,一个用于scp 传输,一个用于删除)。 或者,如果您的 IP 对远程主机可见,请拨打 ssh 在远程主机上运行一个脚本,该脚本会执行所有步骤:转储、存档、scp 到本地计算机、清理. “同步 MongoDB 文件”到底是什么意思? 【参考方案1】:

您可以使用 SSH 隧道来完成此操作,将远程 MongoDB 实例设置为在本地端口之一上运行。默认情况下,MongoDB 在 27017 上运行,因此在下面的示例中,我选择将远程 MongoDB 实例映射到本地 27018 端口。

如果您尝试将数据库从 SERVER1 复制到 LOCALHOST,您可以在您的 LOCALHOST 上运行此命令:

ssh -L27018:localhost:27017 SERVER1

(显然将 SERVER1 替换为您的实际服务器或 ssh 别名)

这会打开到 SERVER1 的 SSH 连接,但也会将 LOCALHOST 上的端口 27018 映射到 SERVER1 上的远程端口 27017。不要关闭该 SSH 连接,现在尝试使用端口 27018 连接到 localhost 机器上的 MongoDB,如下所示:

mongo --port 27018

您会注意到现在这是 SERVER1 上的数据,但您是从本地计算机访问它。

正常运行MongoDB:

mongo(或mongo --port 27107

将是您的本地计算机。

现在,既然您在技术上拥有(在您的 LOCALHOST 上,您运行 SSH 隧道的地方):

27017 上的 MongoDB (LOCALHOST) 27018 上的 MongoDB (SERVER1)

您可以在 MongoDB (LOCALHOST) 中使用 db.copyDatabase() 函数来复制数据。

从 27017 端口上的本地主机(实时执行将删除您的数据)

// Use the right DB
use DATABASENAME; 
// Drop the Existing Data on LOCALHOST
db.dropDatabase();
// Copies the entire database from 27018
db.copyDatabase("DATABASENAME", "DATABASENAME", "localhost:27018");

您应该能够将这一切封装到一个 shell 脚本中,该脚本可以为您执行所有这些命令。我自己也有一个,但它实际上有一些额外的步骤可能会让它更混乱:)

这样做,并使用 MongoDB 的本机 db.copyDatabase() 函数将防止您不得不转储/压缩/恢复。当然,如果你还想走那条路,运行mongodump,导出数据,tar/gzip,然后用scp TARGETSERVER:/path/to/file /local/path/to/file拉下来,运行mongorestore on它。

似乎需要更多的工作!

编辑 - 这是一个 SH 和 JS 文件,它们一起构成一个 shell 脚本,您可以使用它来运行它。 在您的 LOCALHOST 上运行这些,不要在现场运行它们,否则它会在现场运行 db.dropDatabase。将这两个文件放在同一个文件夹中,并将 pull-db.sh 中的 YOURSERVERNAME 替换为 domain/ip/ssh 别名,然后在 pull-db.js 中将 DBNAMEHERE 更改为您的数据库名称。

我通常在我的项目中创建一个名为 scripts 的文件夹,并且使用 Textmate,我只需点击 ⌘+R 同时打开 pull-db.sh 进行编辑以执行它。

pull-db.sh

ssh -L27018:localhost:27017 YOURSERVERNAME '
    echo "Connected on Remote End, sleeping for 10"; 
    sleep 10; 
    exit' &
echo "Waiting 5 sec on local";
sleep 5;
echo "Connecting to Mongo and piping in script";
cat pull-db.js | mongo

pull-db.js

use DBNAMEHERE;
db.dropDatabase();
use DBNAMEHERE;
db.copyDatabase("DBNAMEHERE","DBNAMEHERE","localhost:27018");

我在 shell 脚本中添加了一些额外的代码来回显它在做什么(排序)。脚本中的睡眠计时器只是为了让 SSH 连接有时间在下一行运行之前建立连接。基本上,会发生以下情况:

    代码的第一行在您的机器上创建隧道,并将 ECHO、SLEEP 和 EXIT 发送到远程 SSH 会话。 然后等待 5 秒,这将允许步骤 1 中的 SSH 会话连接。 然后我们将 pull-db.js 文件通过管道传输到本地 mongo shell。 (第 1 步应在 5 秒内完成...) pull-db.js 现在应该在 mongo 中运行,并且步骤 #1 中的 SSH 终端在连接打开后可能已经运行了 10 秒,并且 EXIT 被发送到它的会话。发出命令,但是,SSH 会话实际上将保持打开状态,直到步骤 #3 中的活动完成。 一旦您的 pull-db.js 脚本完成从远程服务器拉取所有数据,在远程服务器上的第 1 步中发出的 EXIT 命令最终被允许关闭连接,解除本地主机上的 27108 绑定。

您现在应该在本地主机中拥有远程数据库中的所有数据。

【讨论】:

我如何在 shell 脚本中执行 copyDatabase 呢?以及如何在脚本结束时退出 SSH 隧道? 使用示例脚本在帖子中添加了更多解释! 这确实是一个很棒的方法!为了减少停机时间,您可能希望使用不同的名称(例如“temp”)复制它,然后在生产机器上“重命名”它,一旦它拥有正确的数据。唯一的“细节”是mongodb仍然没有重命名功能(严重吗??)jira.mongodb.org/browse/SERVER-701 如果您没有运行本地 mongo,您可以将 27017 映射到 27017...所以如果您有任何在本地工作的数据加载脚本,它们将在远程工作【参考方案2】:

我真的不喜欢让一个数据库连接到另一个数据库 - 恕我直言,它打破了环境的分离并使此类脚本自动化变得复杂。

我的解决方案是使用使用“转储目录”的 mongo 转储/恢复,并使用 tar 流式传输文件。一个简单的实现(用于从一个远程复制到另一个远程)可能如下所示:

ssh remote1 'mongodump > /dev/null && tar -zc dump && rm -rf dump' | \
  ssh remote2 'tar -zx && mongorestore dump && rm -rf dump'

注意事项:

    mongodumpmongorestore 都有非常冗长的输出,但是mongodump 都会与 tar 流式传输混淆,而且如果您在没有伪终端的情况下运行,mongodump 实际上会拒绝工作没有输出重定向。 mongodump 有一个转储到标准输出的选项,但我不知道它使用哪种格式,我不明白如何让 mongorestore 加载它。

【讨论】:

非常优雅。在 MongoDB 文档 (>=3.2) 上有一个关于将 mongodump 的标准输出管道传输到 mongorestore 的示例,请参阅docs.mongodb.com/manual/reference/program/mongorestore的“从标准输入还原数据库”部分@ 我很感兴趣,搜索了,找到了,在这里我粘贴了我认为@Derek 提到的实际命令。请注意,此示例取自略有不同的上下文,因此它实际上还将所有 test.* 数据库重命名为 example.* 但管道正在使用中:mongodump --archive --db=test | mongorestore --archive --nsFrom='test.*' --nsTo='examples.*'【参考方案3】:

要完成 Jesta 很好的答案,如果你想做相反的事情(从本地数据库复制到远程数据库),你必须以另一种方式绑定端口,使用 -R 命令而不是 -L 命令:

ssh -R27018:localhost:27017 你的服务器名

现在,登录到远程服务器,您可以从本地数据库复制数据库:

蒙哥

> db.copyDatabase('test','test','localhost:27018')

【讨论】:

以上是关于通过 ssh 同步 MongoDB的主要内容,如果未能解决你的问题,请参考以下文章

通过 ssh 同步 MongoDB

rsync 通过ssh同步以及服务同步

sh 通过ssh同步服务器

十rsync:介绍常用选项通过ssh同步通过服务同步linux系统日志screen

三十 rsync工具介绍rsync常用选项rsync通过ssh同步

三十 rsync工具介绍rsync常用选项rsync通过ssh同步