如何通过shell脚本执行mongo命令?

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

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

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

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

466665 次浏览

把你的mongo脚本放到.js文件中。

然后执行mongo < yourFile.js

例:

Demo.js //file有你的脚本

use sample  //db name
show collections

将此文件保存在“c:\db-scripts”中

然后在cmd提示符中转到"c:\db-scripts"

C:\db-scripts>mongo < demo.js

这将在mongo中执行代码并显示输出

C:\db-scripts>mongo < demo.js
Mongo shell version: 3.0.4
Connecting to: test
switched to db sample
users   //collection name
tasks   //collection name
bye
C:\db-scripts>

把它放在一个名为test.js的文件中:

db.mycollection.findOne()
db.getCollectionNames().forEach(function(collection) {
print(collection);
});

然后用mongo myDbName test.js运行它。

你也可以使用--eval标志来计算一个命令,如果它只是一个命令的话。

mongo --eval "printjson(db.serverStatus())"

请注意:如果你正在使用Mongo操作符,以$符号开始,你需要将eval参数括在单引号中,以防止shell将操作符作为环境变量来计算:

mongo --eval 'db.mycollection.update({"name":"foo"},{$set:{"this":"that"}});' myDbName

否则你可能会看到这样的东西:

mongo --eval "db.test.update({\"name\":\"foo\"},{$set:{\"this\":\"that\"}});"
> E QUERY    SyntaxError: Unexpected token :

这适用于我在Linux下:

mongo < script.js

mongodb的更新版本

mongosh < script.js

下面的shell脚本也很适合我……definite不得不使用Antonin一开始提到的重定向…这让我产生了测试这里文档的想法。

function testMongoScript {
mongo <<EOF
use mydb
db.leads.findOne()
db.leads.find().count()
EOF
}

在我的设置中,我必须使用:

mongo --host="the.server.ip:port" databaseName theScript.js

mongodb的更新版本

mongosh --host="the.server.ip:port" databaseName theScript.js


还有一个官方文档页面关于这个。

该页面的例子包括:

mongo server:27017/dbname --quiet my_commands.js
mongo test --eval "printjson(db.getCollectionNames())"

我使用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>

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

  1. 只有当你试图使mongo shell脚本从命令行可执行时,它才有效。您不能将常规shell命令与mongo shell命令混合使用。这样做所节省的就是不必在命令行上输入“mongo”…(当然有足够的理由)

  2. 它的功能完全类似于“mongo <some-js-file>”,这意味着它不允许您使用“use <db>”命令。

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

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

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

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

这个怎么样:

echo "db.mycollection.findOne()" | mongo myDbName
echo "show collections" | mongo myDbName

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

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

谢谢你printf!在Linux环境中,有一种更好的方法,可以只让一个文件运行。假设你有两个文件,mongoCmds.js有多个命令:

use someDb
db.someColl.find()

然后是驱动程序shell文件runMongoCmds.sh

mongo < mongoCmds.js

更新版本的mongodb

mongosh < mongoCmds.js

相反,只有一个文件runMongoCmds.sh包含

printf "use someDb\ndb.someColl.find()" | mongo

Bash的printfecho健壮得多,并允许命令之间的\n强制它们在多行上。

根据theTuxRacer的建议,你可以使用eval命令,对于那些像我一样缺少它的人,如果你不想对默认db执行form操作,你也可以添加你的db名称。

mongo <dbname> --eval "printjson(db.something.find())"

更新版本的mongodb

mongosh <dbname> --eval "printjson(db.something.find())"
mongo db_name --eval "db.user_info.find().forEach(function(o) {print(o._id);})"

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

mongo < scripts.js > inserts.sql

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

scripts.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), ";");

inserts.sql看起来像这样

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

如果您已启用身份验证:

mongo -u username -p password --authenticationDatabase auth_db_name < your_script.js

更新版本

mongosh -u username -p password --authenticationDatabase auth_db_name < your_script.js

创建一个脚本文件;写命令:

#!/bin/sh
mongo < file.js

对于更新的版本 mongosh & lt;file.js < / p >

file.js中编写mongo查询:

db.collection.find({"myValue":null}).count();

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

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


cat file.sh | mongo <EXPECTED_COLLECTION>
mongo <<EOF
use <db_name>
db.getCollection("<collection_name>").find({})
EOF

在我的例子中,我可以方便地使用\n作为我想要执行的下一个mongo命令的分隔符,然后将它们输送到mongo

echo $'use your_db\ndb.yourCollection.find()' | mongo

更新版本的mongodb

echo $'use your_db\ndb.yourCollection.find()' | mongosh

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

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


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

-S标志可能不能在所有平台上工作。

当使用复制集时,必须在PRIMARY上进行写操作,所以我通常使用这样的语法,以避免弄清楚哪个主机是主主机:

mongo -host myReplicaset/anyKnownReplica

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

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

从编写脚本的shell文档开始:

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