-
-
Save massenz/5694855 to your computer and use it in GitHub Desktop.
| #!/bin/bash | |
| # | |
| # Starts up a MongoDB replica set | |
| # | |
| # There is a lot of documentation about replica sets: | |
| # | |
| # http://docs.mongodb.org/manual/reference/replica-configuration/ | |
| # http://docs.mongodb.org/manual/administration/replica-sets/ | |
| # | |
| # To read data from a SECONDARY, when in the client, use: | |
| # | |
| # > rs.slaveOk() | |
| # | |
| # Created by M. Massenzio, 2012-05-10 | |
| # Prints usage | |
| function usage { | |
| echo "Usage: `basename $0` replicaSetName [num] [port] [host] | |
| Creates a replica set of 'num' MongoDB servers, running on consecutive ports | |
| starting at 'port' on the same 'host' ('localhost' by default). | |
| By default, it will start 3 servers, on ports {27011, 27012, 27013}. | |
| Due to bash limited ability to parse command-line args, each argument MUST | |
| be present, if any of the subsequent ones need to be specified. | |
| The replicaSetName is required and can be used when connecting to | |
| the set, using a URI of the form: | |
| mongodb://host:27011,host:27012,host:27013?replicaSet='replicaSetName' | |
| " | |
| } | |
| # Creates a replica set member's record for the configuration | |
| # | |
| # Arguments: | |
| # $1 id | |
| # $2 host | |
| function create_record { | |
| echo "{ \"_id\": $1, \"host\": \"$2\"}" | |
| } | |
| # Initialize the replica set | |
| # | |
| # Arguments: | |
| # $1 primary mongod port (uses global: HOST) | |
| # $2 replica set configuration record | |
| function initialize_repset { | |
| if [[ -z "$2" ]]; then | |
| echo "No configuration record passed" | |
| exit 1 | |
| fi | |
| local CFG_REC="$2" | |
| echo -e "rsconf = ${CFG_REC}\nrs.initiate(rsconf)" | \ | |
| mongo --port $1 --host ${HOST} > /dev/null | |
| } | |
| # Waits for the state of all mongo servers to get past the STARTUP phases | |
| # | |
| # Arguments: | |
| # $1 a port for the mongo client to connect to (default: 27011) | |
| # $2 the host to connect to (default: localhost) | |
| function wait_for_repset { | |
| local PORT=${1:-27011} | |
| local H=${2:-localhost} | |
| while true; do | |
| num=$(echo "rs.status()" | mongo --port $PORT --host $H | grep stateStr | grep -v STARTUP | wc -l) | |
| if [[ $(expr $num) == ${NUM_REPLICAS} ]]; then | |
| return | |
| fi | |
| sleep 1 | |
| done | |
| } | |
| # Main body of script starts here | |
| # TODO: factor out sub-sections in their own functions | |
| if [[ -z "$1" ]]; then | |
| usage | |
| exit 1 | |
| fi | |
| declare -r REPSET_NAME="$1" | |
| declare -r NUM_REPLICAS=${2:-3} | |
| declare -r STARTING_PORT=${3:-27011} | |
| declare -r HOST=${4:-localhost} | |
| echo "[INFO] Starting ${NUM_REPLICAS} MongoDB servers on ${HOST}, " \ | |
| " using ports starting at ${STARTING_PORT};" \ | |
| " the replica set will be named: ${REPSET_NAME}" | |
| read -p "Do you want to continue (y/N)? " resp | |
| if [[ $resp != 'y' ]]; then | |
| echo "Terminating." | |
| exit 1 | |
| fi | |
| if [[ -z ${MONGO_BASE} ]]; then | |
| echo "[WARN] Please define \$MONGO_BASE to point to where you want data/logs to be created" | |
| MONGO_BASE=${HOME}/mongod_base | |
| read -p "Would you like to continue using the default (${MONGO_BASE})? " resp | |
| if [[ $resp != 'y' ]]; then | |
| echo "Terminating." | |
| exit 1 | |
| fi | |
| fi | |
| echo "Using base directory for logs and data: ${MONGO_BASE}" | |
| declare -r LOGS_DIR="${MONGO_BASE}/logs" | |
| declare -r DATA_DIR="${MONGO_BASE}/data" | |
| mkdir -p ${LOGS_DIR} | |
| echo "Logs sent to ${LOGS_DIR}, data saved in ${DATA_DIR}" | |
| if [[ ! -d ${LOGS_DIR} || ! -d ${DATA_DIR} ]]; then | |
| echo "[ERROR] Either logs or data directory could not be found/created; aborting." | |
| exit 1 | |
| fi | |
| MEMBERS="" | |
| PORT=${STARTING_PORT} | |
| for ((i=1; i <= ${NUM_REPLICAS}; i++)) | |
| do | |
| mkdir -p "${DATA_DIR}/${REPSET_NAME}_${i}" | |
| LOGPATH="${LOGS_DIR}/${REPSET_NAME}_${i}.log" | |
| DBPATH="${DATA_DIR}/${REPSET_NAME}_${i}" | |
| mongod --rest --replSet "${REPSET_NAME}" --logpath $LOGPATH \ | |
| --dbpath $DBPATH --port ${PORT} --fork --vvvvv \ | |
| --smallfiles --oplogSize 128 > /dev/null | |
| echo "[INFO] MongoDB server started on port $PORT" | |
| MEMBERS="$MEMBERS $(create_record $i ${HOST}:${PORT})" | |
| if [[ $i < ${NUM_REPLICAS} ]]; then | |
| MEMBERS="${MEMBERS}," | |
| fi | |
| ((PORT++)) | |
| done | |
| CONFIG="{ _id: \"${REPSET_NAME}\", members: [${MEMBERS}]}" | |
| echo "[INFO] Configuring replica set ${REPSET_NAME} and initializing" | |
| initialize_repset ${STARTING_PORT} "${CONFIG}" | |
| if [[ $? != 0 ]]; then | |
| echo "[ERROR] could not initialize the replica set [${REPSET_NAME}]" | |
| exit 1 | |
| fi | |
| echo "[SUCCESS] Replica set ${REPSET_NAME} started and configured" | |
| echo "[INFO] Waiting for replica set to sync and elect primary..." | |
| wait_for_repset ${STARTING_PORT} ${HOST} | |
| echo "[SUCCESS] To connect to PRIMARY execute: mongo --port ${STARTING_PORT} --host ${HOST}" |
Nice! I was pretty baffled when I saw we absolutely needed to connect to the mongo shell to initiate the replica set, but now I got it!
The only difference between our setups is that I am starting docker containers, instead of instances on localhost with different ports. I will upload my script when it's done!
@mdaftabsmu , I use ansible for this kind of remote deployment. It's a bit of a hassle to learn, but totally worth it, to see your little script spawning tens or hundreds of services remotely! It's basically a toolkit to send SSH commands to a list of servers (that you can create with ansible on AWS or else), using YAML syntax. Good luck!
Ho, dude, I think you forgot to add configsvr: true to CONFIG, as stated here:
The configsvr field must be set to true for the config server replica set.
I know your code seemed to work without, but I guess it must be important!
Hi sir ,
I am trying to create mogodb replica set remotely as service
Could you sir guide me step -by -step ..
I have to done remotely using terminal but I have to stuck as service