Today, I’m going to share with you a bash script that gives you a quick overview of the topology of your MongoDB cluster.
It will give you:
- The list and status of your mongos
- The list and status of your config server
- The list and status of every replica set members present in your cluster (including secondary members and arbiters), plus:
- The date of the last role change between primary and secondary
- The apply lag between primary and all secondary members
- The oplog window
- The balancer status
You can download the script on my GitHut repository “MyDBAWorld”.
Prerequisites
- JQ (If you’re not familiar with JQ, check out my previous article about parsing JSON with JQ)
- A MongoDB sharded cluster
- A user on each local shard and on the cluster with, at least, the following privileges:
- Read on “admin” database
- Read on “config” database
- “clusterMonitor” role
Because MongoDB does not provide any mechanisms to store encrypted password as Oracle do with wallets, I recommend you to not use a user with too much privileges (sadly, passwords will be stored in the script…).
The script has been tested on MongoDB 3.4 and 3.6 on Debian 8 (jessie) and Red Hat Enterprise Linux Server 7.3 (Maipo). Since there are no major changes in later versions of MongoDB with the commands / collections used by the script, this should work.
Configuration
You need to fill seven variables at the top of the script:
- CLUSTERADMINUSR: the cluster user you want to use
- CLUSTERADMINPWD: the password for the cluster user
- CLUSTERAUTHDB: the authentication database for that user
- LOCALADMINUSR: the local user you want to use (it must be present on all members of your replica set)
- LOCALADMINPWD: the password for the local user (it must be the same on all members of your replica set)
- LOCALAUTHDB: the authentication database for that user
- FIRSTMONGOS: the hostname and port of one of your mongos (router). The format must be: “hostname:port”
For example:
CLUSTERADMINUSR="cluster_admin" CLUSTERADMINPWD="cluster_password" CLUSTERAUTHDB="admin" LOCALADMINUSR="local_admin" LOCALADMINPWD="local_password" LOCALAUTHDB="admin" FIRSTMONGOS="mongodocker1:27017"
Once done, you can execute the script as usual.
Sample output
Here is a sample output of the script executed against my MongoDB cluster composed of 6 shards, 3 config server and 3 mongos. Each shard is composed of 1 primary, 1 secondary and 1 arbiter, except shard “rs01” on which I have 1 primary and 2 secondary members.
Copy/paste does not preserve the colors, but “UP” will be written in green, “DOWN” in red and “TIMEOUT” in yellow to allow to see quickly if something is wrong.
#### Config DB list #### mongodocker1:27019 : SECONDARY : UP mongodocker2:27019 : PRIMARY : UP mongodocker3:27019 : SECONDARY : UP Balancer enabled : true #### Mongos list #### mongodocker1:27017 : UP mongodocker2:27017 : UP mongodocker3:27017 : UP #### Shards list #### [Shard : rs05] mongodocker2:27021 : ARBITER : UP mongodocker5:27018 : SECONDARY : UP mongodocker6:27020 : PRIMARY : UP --Last switch: 06/12/2018 15:37:18 --Apply lag: mongodocker5:27018 is 0 second(s) behind primary mongodocker6:27020 --Oplog window: 108 days, 23 Hours, 20 Minutes, 27 Seconds [Shard : rs03] mongodocker6:27021 : ARBITER : UP mongodocker3:27018 : PRIMARY : UP mongodocker4:27020 : SECONDARY : UP --Last switch: 06/12/2018 15:10:31 --Apply lag: mongodocker4:27020 is 0 second(s) behind primary mongodocker3:27018 --Oplog window: 108 days, 23 Hours, 23 Minutes, 57 Seconds [Shard : rs06] mongodocker4:27021 : ARBITER : UP mongodocker5:27020 : SECONDARY : UP mongodocker6:27018 : PRIMARY : UP --Last switch: 07/12/2018 04:26:05 --Apply lag: mongodocker5:27020 is 0 second(s) behind primary mongodocker6:27018 --Oplog window: 108 days, 23 Hours, 18 Minutes, 36 Seconds [Shard : rs04] mongodocker5:27021 : ARBITER : UP mongodocker1:27018 : SECONDARY : UP mongodocker2:27020 : PRIMARY : UP --Last switch: 06/12/2018 15:37:04 --Apply lag: mongodocker1:27018 is 0 second(s) behind primary mongodocker2:27020 --Oplog window: 108 days, 23 Hours, 22 Minutes, 9 Seconds [Shard : rs02] mongodocker1:27021 : ARBITER : UP mongodocker2:27018 : PRIMARY : UP mongodocker3:27020 : SECONDARY : UP --Last switch: 06/12/2018 15:37:18 --Apply lag: mongodocker3:27020 is 0 second(s) behind primary mongodocker2:27018 --Oplog window: 108 days, 23 Hours, 26 Minutes, 16 Seconds [Shard : rs01] mongodocker1:27020 : PRIMARY : UP mongodocker3:27021 : SECONDARY : UP mongodocker4:27018 : SECONDARY : UP --Last switch: 06/12/2018 15:37:19 --Apply lag: mongodocker4:27018 is 0 second(s) behind primary mongodocker1:27020 mongodocker3:27021 is 0 second(s) behind primary mongodocker1:27020 --Oplog window: 108 days, 23 Hours, 29 Minutes, 2 Seconds
The date format is “DD/MM/YYYY HH:MI:SS”. If you want US date format, you can replace the line
LASTSWITCH=$(RunOnMongo "${PRIMARY}" "var d=db.runCommand('isMaster').electionId.getTimestamp();var yyyy = d.getFullYear();var mm = (d.getMonth() + 101).toString().slice(-2);var dd = (d.getDate() + 100).toString().slice(-2);var hh = ('0'+d.getHours()).slice(-2);var mi = ('0'+d.getMinutes()).slice(-2);var ss = ('0'+d.getSeconds()).slice(-2);print(dd + '/' + mm+'/'+yyyy+' '+hh+':'+mi+':'+ss);" "2")
with
LASTSWITCH=$(RunOnMongo "${PRIMARY}" "var d=db.runCommand('isMaster').electionId.getTimestamp();var yyyy = d.getFullYear();var mm = (d.getMonth() + 101).toString().slice(-2);var dd = (d.getDate() + 100).toString().slice(-2);var hh = ('0'+d.getHours()).slice(-2);var mi = ('0'+d.getMinutes()).slice(-2);var ss = ('0'+d.getSeconds()).slice(-2);print(mm + '/' + dd+'/'+yyyy+' '+hh+':'+mi+':'+ss);" "2")
I hope you find this script useful!