I recently wrote a small script to deploy a mongodb cluster on a single machine. The cluster is composed of :
- 3 configurations server that holds the same informations (they are replicas )
- 2 shard server wich will store the data
- one mongos which manage connection to the cluster
The script parse a configuration file holding the cluster configuration, and then starts the different member in a specific order.
Here is the config file:
#config file to store host and port
#config server list, in folowing format:
# config=<host>:<port>
# started with --dbpath /data/configX where
# X is the position of the server in the list
config=localhost:27018
config=localhost:27019
config=localhost:27020
#mongos instance in folowing format:
# mongos=<host>:<port>
mongos=localhost:27017
#shard list in folowinf format:
# shard=<host>:<port>
# started with --dbpath /data/shardX where
# X is the position of the shard in the list
shard=localhost:27021
shard=localhost:27022
and here is the script:
#!/bin/bash
# this script should be launched on the server where you want the
# mongos to run. It should be run like this:
# ./deploy.sh path/to/config.txt
# make sure that mongod, mongos and mongo are linked correctly
# you can achieved this using the following command:
# sudo ln -s /path/to/mongo/bin/mongo /bin/mongo
# host:port for config server
CONFIG=()
# host:port for shards
SHARD=()
# text colors
red=`tput setaf 1`
green=`tput setaf 2`
reset=`tput sgr0`
# clear log file
echo "" > log.txt
# ignore empty or comment line
sed '/^#/d;/^$/d' $1 |
{
while read -r line
do
IFS='=' read -a array <<< "$line"
val="${array[1]}"
key="${array[0]}"
if [ "$key" == "config" ]; then
CONFIG+=("$val")
echo "mongod config server: $val"
fi
if [ "$key" == "mongos" ]; then
MONGOS="$val"
echo "mongos instance: $val"
fi
if [ "$key" == "shard" ]; then
SHARD+=("$val")
echo "shard instance: $val"
fi
done
#start config servers
index=0
for conf in "${CONFIG[@]}"
do
# ping each host to make sure it's reacheable
IFS=':' read -a config <<< ${CONFIG[$index]}
mkdir /data/config$index
echo "starting config server $index"
mongod --configsvr --port ${config[1]} --dbpath /data/config$index --replSet conf > log.txt&
index=$(($index + 1))
sleep 1
done
sleep 10
echo "${green}config servers deployed${reset}"
# setup the config replica set. Only neccessary on first launch
IFS=':' read -a config0 <<< ${CONFIG[0]}
mongo --host ${config0[0]} --port ${config0[1]} --eval "rs.initiate( { _id: \"conf\", members: [ {_id: 0, host:\"${CONFIG[0]}\"}, {_id: 1, host:\"${CONFIG[1]}\"}, {_id: 2, host:\"${CONFIG[2]}\"} ]})"&
# sleep so a primary shard can be designed among config servers
sleep 15
# get mongos infos
IFS=':' read -a mongos <<< $MONGOS
#start mongos
mongos --port ${mongos[1]} --configdb "conf/${CONFIG[0]},${CONFIG[1]},${CONFIG[2]}" > log.txt&
echo "${green}mongos instance configured${reset}"
sleep 5
# start each shard and add them to the cluster
shardnb=0
for shard in "${SHARD[@]}"
do
IFS=':' read -a sh <<< ${SHARD[$shardnb]}
mkdir /data/shard$shardnb
echo "starting shard $shardnb"
mongod --shardsvr --port ${sh[1]} --dbpath /data/shard$shardnb > log.txt&
sleep 5
mongo --host ${mongos[0]} --port ${mongos[1]} --eval "sh.addShard(\"$shard\");"&
sleep 5
shardnb=$(($shardnb + 1))
echo "${green}shard $shard added${reset}"
done
# make sure that the sharded cluster has been deployed correctly
mongo --host ${mongos[0]} --port ${mongos[1]} --eval "sh.status();"
}
I use this to quickly deploy a cluster in a docker container in order to run automated integration test. As this is one of my first bach script, I'm looking for advises on style / readability !
$()instead of backticks, it is the current POSIX standard and is better for several reasons: Your tput lines should change fromred=tput setaf 1` tored=$(tput setaf 1)\$\endgroup\$