MongoDB command line to show if a user exists (for puppet 'unless' clause) - mongodb

We are using MongoDB user based authentication, and I want to quickly run a command to check whether a user has already been created in the database, in order that puppet won't repeatedly attempt to create the user.
Here is how we check if the replica set has initialised:
/usr/bin/mongo --host ${members[0]} --quiet --eval 'rs.status().ok' | grep -q 1
Is a similar trick possible with authentication? I've checked the documentation here http://www.mongodb.org/display/DOCS/dbshell+%28mongo%29+Reference and I can't see a way of doing it?

Yes, on a given DB, you can use db.system.users.find({user:'login'}).count() which will return 0 if the user does not exist.

It feels that this method has been deprecated, I needed the following command to work:
db.getUsers({filter: {'user': 'login'}})

Today I just tried -u and -p options for mongo command and it worked for me:
mongo --port 27037 --quiet -u superuser -p pwd
--eval "db.system.users.find({user:'user3'}).count()" admin
Note the last "admin" arg - it is the name of database, to which you are authenticating.

To check if a user username exists:
db.runCommand({ usersInfo: { user: "username", db: "admin" } }).users.length == 1
This will return true if the user exists, and false otherwise. (If the user was created in another database, replace admin with the name of the database.)

You can also use findOne
db.system.users.findOne({user:'login'})
it will null if no user
it will return user if found

Related

Delete MongoDB database from Bash script

I'm not a Bash/Linux person, but I've been asked to just come up with the lines needed to run to authenticate against a database and then drop it. Here is what I have so far and I'm not sure if it's correct:
mongo mydatabase –port –username <username> –password <password> –authenticationDatabase admin –eval “ printjson(db.dropDatabase())”
If it's possible to use one line to delete any database whose name starts with "cpt_" then that would be absolutely ideal.
Thanks!
You can use -
Get all the names
Loop and check if the name starts with cpt_
drop the database
db.getMongo().getDBNames().forEach(function(dbName){ if (dbName.startsWith('cpt_')) printjson(db.getSiblingDB(dbName).dropDatabase())
Full
mongo –port –username <username> –password <password> –authenticationDatabase admin --eval "db.getMongo().getDBNames().forEach(function(dbName){ if (dbName.startsWith('cpt_')) printjson(db.getSiblingDB(dbName).dropDatabase()) })"

How can I disable connection messages in mongo shell [duplicate]

I want to execute mongo commands in shell script, e.g. in a script test.sh:
#!/bin/sh
mongo myDbName
db.mycollection.findOne()
show collections
When I execute this script via ./test.sh, then the connection to MongoDB is established, but the following commands are not executed.
How to execute other commands through shell script test.sh?
You can also evaluate a command using the --eval flag, if it is just a single command.
mongo --eval "printjson(db.serverStatus())"
Please note: if you are using Mongo operators, starting with a $ sign, you'll want to surround the eval argument in single quotes to keep the shell from evaluating the operator as an environment variable:
mongo --eval 'db.mycollection.update({"name":"foo"},{$set:{"this":"that"}});' myDbName
Otherwise you may see something like this:
mongo --eval "db.test.update({\"name\":\"foo\"},{$set:{\"this\":\"that\"}});"
> E QUERY SyntaxError: Unexpected token :
Put your mongo script into a .js file.
Then execute mongo < yourFile.js
Ex:
demo.js //file has your script
use sample //db name
show collections
keep this file in "c:\db-scripts"
Then in cmd prompt go to "c:\db-scripts"
C:\db-scripts>mongo < demo.js
This will execute the code in mongo and shows the output
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>
This works for me under Linux:
mongo < script.js
For newer version of mongodb
mongosh < script.js
Put this in a file called test.js:
db.mycollection.findOne()
db.getCollectionNames().forEach(function(collection) {
print(collection);
});
then run it with mongo myDbName test.js.
There is an official documentation page about this as well.
Examples from that page include:
mongo server:27017/dbname --quiet my_commands.js
mongo test --eval "printjson(db.getCollectionNames())"
The shell script below also worked nicely for me... definite had to use the redirect that Antonin mentioned at first... that gave me the idea to test the here document.
function testMongoScript {
mongo <<EOF
use mydb
db.leads.findOne()
db.leads.find().count()
EOF
}
In case you have authentication enabled:
mongo -u username -p password --authenticationDatabase auth_db_name < your_script.js
For newer version
mongosh -u username -p password --authenticationDatabase auth_db_name < your_script.js
I use the "heredoc" syntax, which David Young mentions. But there is a catch:
#!/usr/bin/sh
mongo <db> <<EOF
db.<collection>.find({
fieldName: { $exists: true }
})
.forEach( printjson );
EOF
The above will NOT work, because the phrase "$exists" will be seen by the shell and substituted with the value of the environment variable named "exists." Which, likely, doesn't exist, so after shell expansion, it becomes:
#!/usr/bin/sh
mongo <db> <<EOF
db.<collection>.find({
fieldName: { : true }
})
.forEach( printjson );
EOF
In order to have it pass through you have two options. One is ugly, one is quite nice. First, the ugly one: escape the $ signs:
#!/usr/bin/sh
mongo <db> <<EOF
db.<collection>.find({
fieldName: { \$exists: true }
})
.forEach( printjson );
EOF
I do NOT recommend this, because it is easy to forget to escape.
The other option is to escape the EOF, like this:
#!/usr/bin/sh
mongo <db> <<\EOF
db.<collection>.find({
fieldName: { $exists: true }
})
.forEach( printjson );
EOF
Now, you can put all the dollar signs you want in your heredoc, and the dollar signs are ignored. The down side: That doesn't work if you need to put shell parameters/variables in your mongo script.
Another option you can play with is to mess with your shebang. For example,
#!/bin/env mongo
<some mongo stuff>
There are several problems with this solution:
It only works if you are trying to make a mongo shell script executable from the command line. You can't mix regular shell commands with mongo shell commands. And all you save by doing so is not having to type "mongo" on the command line... (reason enough, of course)
It functions exactly like "mongo <some-js-file>" which means it does not let you use the "use <db>" command.
I have tried adding the database name to the shebang, which you would think would work. Unfortunately, the way the system processes the shebang line, everything after the first space is passed as a single parameter (as if quoted) to the env command, and env fails to find and run it.
Instead, you have to embed the database change within the script itself, like so:
#!/bin/env mongo
db = db.getSiblingDB('<db>');
<your script>
As with anything in life, "there is more than one way to do it!"
In my setup I have to use:
mongo --host="the.server.ip:port" databaseName theScript.js
For newer version of mongodb
mongosh --host="the.server.ip:port" databaseName theScript.js
How about this:
echo "db.mycollection.findOne()" | mongo myDbName
echo "show collections" | mongo myDbName
Create a script file; write commands:
#!/bin/sh
mongo < file.js
For newer versions
mongosh < file.js
In file.js write your mongo query:
db.collection.find({"myValue":null}).count();
As suggested by theTuxRacer, you can use the eval command, for those who are missing it like I was, you can also add in your db name if you are not trying to preform operation on the default db.
mongo <dbname> --eval "printjson(db.something.find())"
Newer version of mongodb
mongosh <dbname> --eval "printjson(db.something.find())"
In my case, I can conveniently use \n as separator for the next mongo command I want to execute then pipe them to mongo
echo $'use your_db\ndb.yourCollection.find()' | mongo
Newer version of mongodb
echo $'use your_db\ndb.yourCollection.find()' | mongosh
Thank you printf! In a Linux environment, here's a better way to have only one file run the show. Say you have two files, mongoCmds.js with multiple commands:
use someDb
db.someColl.find()
and then the driver shell file, runMongoCmds.sh
mongo < mongoCmds.js
Newer version of mongodb
mongosh < mongoCmds.js
Instead, have just one file, runMongoCmds.sh containing
printf "use someDb\ndb.someColl.find()" | mongo
Bash's printf is much more robust than echo and allows for the \n between commands to force them on multiple lines.
mongo <<EOF
use <db_name>
db.getCollection("<collection_name>").find({})
EOF
--shell flag can also be used for javascript files
mongo --shell /path/to/jsfile/test.js
mongo db_name --eval "db.user_info.find().forEach(function(o) {print(o._id);})"
Recently migrated from mongodb to Postgres. This is how I used the scripts.
mongo < scripts.js > inserts.sql
Read the scripts.js and output redirect to inserts.sql.
scripts.js looks like this
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 looks like this
INSERT INTO table(a, b) VALUES('abc', 'Alice'), ('def', 'Bob'), ('ghi', 'Claire');
If you want to handle it with one line it's an easy way.
file.sh --> db.EXPECTED_COLLECTION.remove("_id":1234)
cat file.sh | mongo <EXPECTED_COLLECTION>
Single shell script solution with ability to pass mongo arguments (--quiet, dbname, etc):
#!/usr/bin/env -S mongo --quiet localhost:27017/test
cur = db.myCollection.find({});
while(cur.hasNext()) {
printjson(cur.next());
}
The -S flag might not work on all platforms.
When using a replicaset, writes must be done on the PRIMARY, so I usually use syntax like this which avoids having to figure out which host is the master:
mongo -host myReplicaset/anyKnownReplica
The legacy mongo shell has been removed from MongoDB with the version 6 release in 2022
There is a new way to execute shell scripts using the new shell, mongosh
From the shell documentation on writing scripts:
You can use mongosh to execute a script from the command line without entering the mongosh console
To specify the filename, use the --file or -f parameter to specify the filename
You may also need to specify connection information

Using mongodump to create a single file for each mongo database

I am attempting to create a single archive file for each database in Mongo. Is there a way to create a batch file that will automatically create an archive (.archive) for each database without me manually entering the database name?
The snipet provided
mongodump --host hostename --port portname --username username --password password --authenticationDatabase admin --db databasename --archive=name.arvhive
I would like to create the archive file without having to specify the database name. Is this possible? If not, is there a way to dump all of the databases and create a single gzip for each database?
Any assistance would be greatly appreciated.
Thanks!
In order to get the DB names in the mongo instance we need to use the mongo show dbs command.
Since we want to be able to use this inside a script, we want to run that command and exit the mongo cli, to do that we can pass a js file to mongo, like so:
$ echo "show dbs" > showDbs.js
$ mongo < showDbs.js
Which will result in something like
MongoDB shell version v3.4.22
connecting to: mongodb://127.0.0.1:27017
MongoDB server version: 3.4.22
admin 0.000GB
animals 0.366GB
people 0.012GB
local 0.000GB
bye
Since we need to parse the result, we can use the --quiet option to reduce the output. We can also skip creating the showDbs.js file so that we don't have to clean it up later.
Now we have:
$ mongo --quiet <<< "show dbs"
admin 0.000GB
animals 0.366GB
people 0.012GB
local 0.000GB
All that's left to do is to parse the result to remove the db sizes, and then run the mongodump command for each of the databases (I'm leaving that command as it is)
To remove the size information for each database we'll use sed and match for a whitespace, since whitespaces are not allowed in database names
$ sed 's/\s\+.\+//' <<< "$dbs"
Putting it all together we get the following script
#!/bin/bash
dbs=$(mongo --quiet <<< "show dbs")
dbs=$(sed 's/\s\+.\+//' <<< "$dbs")
for db in $dbs; do
mongodump --host hostname --port portname --username username --password password --authenticationDatabase admin --db $db --archive=$db.archive
done

Create a MongoDB user from commandline

I have set up a MongoDB database with an admin user that has only administrative rights, not read or write access to databases.
What I now would want to do is:
Add a new database,
and add a new user to that database.
And: I need to do this from the command line. So I tried:
$ mongo admin -u admin -p admin --eval "db.addUser('dummyuser', 'dummysecret')"
(Please note that as I am still running MongoDB 2.0, I am using the old format of db.addUser.)
This would make perfect sense if I could also tell it which database this user should be for. But now I am struggling. How do I specify the database for this command? If I were in the interactive shell, I could just run
> use dummydb
but how do I do this from the command line? My first try was to concatenate both commands with a ;, but this didn't work:
$ mongo admin -u admin -p admin --eval "use dummydb;db.addUser('dummyuser', 'dummysecret')"
just gives me syntax error.
How do I get this right?
The use db syntax is only supported in an interactive shell session.
If you want to change databases from an admin script, you can use db.getSiblingDB('dbname').
So your equivalent command line using --eval would be:
# MongoDB 2.6+: use createUser()
$ mongo admin -u admin -p admin --eval "db.getSiblingDB('dummydb').createUser({user: 'dummyuser', pwd: 'dummysecret', roles: ['readWrite']})"
# MongoDB 2.4: use addUser()
$ mongo admin -u admin -p admin --eval "db.getSiblingDB('dummydb').addUser('dummyuser', 'dummysecret')"
There is a section in the MongoDB manual covering Differences between interactive and scripted mongo. This includes equivalents for other interactive shell helpers such as show dbs and show collections.
Solved it by putting the commands
use dummydb
db.addUser('dummyuser', 'dummysecret')
into a .js file, and then ran MongoDB by calling:
$ mongo admin -u admin -p admin < setupMongoDB.js
That's it :-)
Above in my case didn't worked
use dummyDb
db.createUser({user: "admin",pwd: "secrectP#wd",roles: [ { role: "readWrite", db: "reporting" } ],mechanisms: [ "SCRAM-SHA-256" ] }

How do I drop a MongoDB database from the command line?

What's the easiest way to do this from my bash prompt?
Like this:
mongo <dbname> --eval "db.dropDatabase()"
More info on scripting the shell from the command line here: https://docs.mongodb.com/manual/tutorial/write-scripts-for-the-mongo-shell/#scripting
Edit:
In Mongo 6.0 mongo was removed and replaced with mongosh which has to be installed separately. More info here: https://www.mongodb.com/docs/mongodb-shell/#mongodb-binary-bin.mongosh
The best way to do it is from the mongodb console:
> use mydb;
> db.dropDatabase();
Alternatively, you can stop mongod and delete the data files from your data directory, then restart.
Hint: you can also move the data files to a subfolder, and delete them if you're sure you no longer need them.
I found this easy to remember:
mongo //to start the mongodb shell
show dbs //to list existing databases
use <dbname> //the <dbname> is the database you'd like to drop
db //should show <dbname> just to be sure I'm working with the right database
db.dropDatabase() //will delete the database & return { "dropped" : "<dbname>", "ok" : 1 }
You don't need heredocs or eval, mongo itself can act as an interpreter.
#!/usr/bin/env mongo
var db = new Mongo().getDB("someDatabase");
db.dropDatabase();
Make the file executable and run it.
Start MongoDB
Command for Database drop is :
1. first select the database which you want to delete
use < database name >
2. Then use this..
db.dropDatabase()
You could also use a "heredoc":
mongo localhost/db <<EOF
db.dropDatabase()
EOF
Results in output like:
mongo localhost/db <<EOF
db.dropDatabase()
EOF
MongoDB shell version: 2.2.2
connecting to: localhost/db
{ "dropped" : "db", "ok" : 1 }
bye
I like to use heredocs for things like this, in case you want more complex sequence of commands.
Here are some use full delete operations for mongodb using mongo shell
To delete particular document in collections: db.mycollection.remove( {name:"stack"} )
To delete all documents in collections: db.mycollection.remove()
To delete collection : db.mycollection.drop()
to delete database :
first go to that database by use mydb command and then
db.dropDatabase()
directly from command prompt or blash : mongo mydb --eval "db.dropDatabase()
Other way:
echo "db.dropDatabase()" | mongo <database name>
Execute in a terminal:
mongo // To go to shell
show databases // To show all existing databases.
use <DATA_BASE> // To switch to the wanted database.
db.dropDatabase() // To remove the current database.
Open another terminal window and execute the following commands,
mongodb
use mydb
db.dropDatabase()
Output of that operation shall look like the following
MAC:FOLDER USER$ mongodb
> show databases
local 0.78125GB
mydb 0.23012GB
test 0.23012GB
> use mydb
switched to db mydb
>db.dropDatabase()
{ "dropped" : "mydb", "ok" : 1 }
>
Please note that mydb is still in use, hence inserting any input at that time will initialize the database again.
Open a terminal and type:
mongo
The below command should show the listed databases:
show dbs
/* the <dbname> is the database you'd like to drop */
use <dbname>
/* the below command will delete the database */
db.dropDatabase()
The below should be the output in the terminal:
{
"dropped": "<dbname>",
"ok": 1
}
Using Javascript, you can easily create a drop_bad.js script to drop your database:
create drop_bad.js:
use bad;
db.dropDatabase();
Than run 1 command in terminal to exectue the script using mongo shell:
mongo < drop_bad.js
Eventhough there are several methods, The best way (most efficient and easiest) is using db.dropDatabase()
In you command prompt, First connect to mongodb using following command:
mongo -h [host-name]:[port:number] -d [dbname] -u [username] -p [password]
you will be accessing db with <dbname>.
Run the following command to drop the whole database:
db.dropDatabase()
one liner remote remove all collections from mongo database
note must use --host, (-h is help for mongo command), and -d is not an option, select the db and command after password.
mongo --host <mongo_host>:<mongo_port> -u <db_user> -p <db_pass> <your_db> --eval "db.dropDatabase()"
Surprised that we haven't seen this variation come up. This minimizes extra args on the command line and explicitly shows the DB being switched to FOO and then dropped:
$ mongo --host "mongodb://machine:port" --eval 'db.getSiblingDB("FOO").dropDatabase();'
LogIn into your mongoDB command line:
And type the below commands.
use "YOUR_DATABASE_NAME";
db.dropDatabase();
Drop a MongoDB database using python:
import argparse
import pymongo
if __name__ == "__main__":
"""
Drop a Database.
"""
parser = argparse.ArgumentParser()
parser.add_argument("--host", default='mongodb://localhost:27017',
help="mongodb URI [default: %(default)s]")
parser.add_argument("--database", default=None,
help="database name: %(default)s]")
args = parser.parse_args()
client = pymongo.MongoClient(host=args.host)
if args.database in client.list_database_names():
client.drop_database(args.database)
print(f"Dropped: '{args.database}'")
else:
print(f"Database '{args.database}' does not exist")
In order to be really sure that you drop the correct database use
mongo <connection properties> --eval "db.getSiblingDB('dbname').dropDatabase()"
See Authentication failure while trying to save to mongodb to understand the concerns.
You can first switch to your database which you want to delete. Then you can delete the same by using the command dropDatabase().
Code :
>use dbName
>db.dropdataBase()
The result will be :
{ "dropped" : "dbName", "ok" : 1 }
If you want to delete a specific collection in a database, then switch to the database and enter the following command.
Code:
>use dbName
db.collection.drop()
The result will be :
true
If you want a better understanding of MongoDB shell commands it's
better to follow the documentation always.
Link to the documentation :
https://www.mongodb.com/docs/manual/reference/method/#std-label-js-administrative-methods
db will show the current Database name
type: db.dropDatabase();
1- select the database to drop by using 'use' keyword.
2- then type db.dropDatabase();
use following command from mongo shell to drop db
use <database name>;
db.dropDatabase();