我想在shell脚本中执行mongo命令,例如在脚本test.sh中:

#!/bin/sh
mongo myDbName
db.mycollection.findOne()
show collections

当我通过./test.sh执行这个脚本时,会建立到MongoDB的连接,但不会执行以下命令。

如何通过shell脚本test.sh执行其他命令?


当前回答

——shell标志也可以用于javascript文件

 mongo --shell /path/to/jsfile/test.js 

其他回答

最近从mongodb迁移到Postgres。这是我使用脚本的方式。

mongo < scripts.js > inserts.sql

读取scripts.js,输出重定向到inserts.sql。

js看起来像这样

use myDb;
var string = "INSERT INTO table(a, b) VALUES";
db.getCollection('collectionName').find({}).forEach(function (object) {
    string += "('" + String(object.description) + "','" + object.name + "'),";
});
print(string.substring(0, string.length - 1), ";");

插入。SQL看起来像这样

INSERT INTO table(a, b) VALUES('abc', 'Alice'), ('def', 'Bob'), ('ghi', 'Claire');

单shell脚本解决方案,能够传递mongo参数(——quiet, dbname,等):

#!/usr/bin/env -S mongo --quiet localhost:27017/test

cur = db.myCollection.find({});
while(cur.hasNext()) {
  printjson(cur.next());
}

-S标志可能不适用于所有平台。

我使用David Young提到的“heredoc”语法。但这里有一个问题:

#!/usr/bin/sh

mongo <db> <<EOF
db.<collection>.find({
  fieldName: { $exists: true }
})
.forEach( printjson );
EOF

上面的代码将不起作用,因为shell将看到短语“$exists”,并将其替换为名为“exists”的环境变量的值。它很可能不存在,所以在shell扩展之后,它变成:

#!/usr/bin/sh

mongo <db> <<EOF
db.<collection>.find({
  fieldName: { : true }
})
.forEach( printjson );
EOF

为了让它通过你有两个选择。一个很丑,一个很好。首先是最丑的:转义$符号:

#!/usr/bin/sh

mongo <db> <<EOF
db.<collection>.find({
  fieldName: { \$exists: true }
})
.forEach( printjson );
EOF

我不建议这样做,因为很容易忘记逃避。

另一个选择是转义EOF,就像这样:

#!/usr/bin/sh

mongo <db> <<\EOF
db.<collection>.find({
  fieldName: { $exists: true }
})
.forEach( printjson );
EOF

现在,你可以在heredoc中放入任何你想要的美元符号,美元符号会被忽略。缺点:如果你需要在mongo脚本中放置shell参数/变量,这是行不通的。

另一个你可以玩的选择是弄乱你的“shebang”。例如,

#!/bin/env mongo
<some mongo stuff>

这种解决方案存在几个问题:

只有当你试图使mongo shell脚本从命令行可执行时,它才有效。您不能将常规shell命令与mongo shell命令混合使用。这样做所节省的就是不必在命令行上输入“mongo”…(当然有足够的理由) 它的功能完全类似于“mongo <some-js-file>”,这意味着它不允许您使用“use <db>”命令。

我尝试将数据库名称添加到shebang中,您可能认为这可以工作。不幸的是,根据系统处理shebang行的方式,第一个空格之后的所有内容都作为单个参数(好像加了引号)传递给env命令,env无法找到并运行它。

相反,你必须将数据库更改嵌入到脚本本身中,如下所示:

#!/bin/env mongo
db = db.getSiblingDB('<db>');
<your script>

就像生活中的任何事情一样,“做这件事的方法不止一种!”

如果你想用一条线来处理它,这是一个简单的方法。

file.sh --> db.EXPECTED_COLLECTION.remove("_id":1234)

cat file.sh | mongo <EXPECTED_COLLECTION>

遗留的mongo shell已从MongoDB中移除,并将于2022年发布第6版

有一种使用新shell mongosh执行shell脚本的新方法

来自编写脚本的shell文档:

您可以使用mongosh从命令行执行脚本,而无需进入mongosh控制台 要指定文件名,请使用——file或-f参数指定文件名 您可能还需要指定连接信息