通过 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'
注意事项:
mongodump
和 mongorestore
都有非常冗长的输出,但是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的主要内容,如果未能解决你的问题,请参考以下文章
十rsync:介绍常用选项通过ssh同步通过服务同步linux系统日志screen