killamanjaro98
killamanjaro98

Reputation: 23

Detecting when Mongod's port is open inside a script

I'm trying to write a bash script that starts a mongod process, waits for it to start (i.e. have it's default port open) and then pipe some commands into it through the mongo shell. I'd like some way to wait for the mongod process to be completely up that's more deterministic than just sleep 5.

This is the script so far:

set_up_authorization() {
    echo "Setting up access control"
    /path/to/mongo < configure_access_controls.js
}

wait_for_mongod_to_start() {
    RETRIES=1000
    CONNECTED="false"
    echo "Waiting for mongod to start"
    while [[ $RETRIES -ge 0 && $CONNECTED == "false" ]] ; do
        RESPONSE=$(exec 6<>/dev/tcp/127.0.0.1/27017 || echo "1")
        if [[ $RESPONSE == "" ]] # which should happen if the exec is successful
            CONNECTED="true"
        fi
        RETRIES=$((RETRIES - 1))
    done
    if [[ $RETRIES -eq 0 ]] ; then
        echo "Max retries reached waiting for mongod to start. Exiting."
        exit 1
    fi
    echo "Mongod started"
}

./start_mongod_instance.sh
wait_for_mongod_to_start
set_up_authorization

While this script works, it produces a ton of output on the terminal while the exec is failing:

./initialize_cluster.sh: connect: Connection refused
./initialize_cluster.sh: line xx: /dev/tcp/127.0.0.1/27017: Connection refused

...which repeats for all ~900 failed attempts.

Neither of the following seems to get rid of the terminal logging either:

exec 6<>/dev/tcp/127.0.0.1/27017 >/dev/null
OR
exec 6<>/dev/tcp/127.0.0.1/27017 2>/dev/null

I've also tried using the following:

ps -aux | grep "mongod" | wc -l 

but the process having a pid that ps lists isn't equivalent to it's port being open or it accepting connections.

Any ideas on either front would be appreciated - a more elegant way to wait for the process to start completely or a way to get rid of the excessive logging to the terminal.

Note: I don't have access to nmap or nc to check the port (this is on a client's machine).

Upvotes: 1

Views: 165

Answers (1)

hek2mgl
hek2mgl

Reputation: 158250

exec is a bit special. It affects the output of the current shell. Meaning you need to redirect stderr of the current shell before running the port check:

host="localhost"
port="9000"
exec 2>/dev/null # redirect error here
while ! exec 3<>"/dev/tcp/${host}/${port}" ; do
    echo "Waiting ..."
    sleep 1
done

Furthermore you might have noticed that I check the exit status of exec rather than some output to decide whether the port is open or not.


If you want to reset it afterwards:

host="localhost"
port="9000"

# Copy fd 2 into fd 3 and redirect fd 2 to /dev/null
exec 3<&2 2>/dev/null

while ! exec 3<>"/dev/tcp/${host}/${port}" ; do
    echo "Waiting ..."
    sleep 1
done

# Copy back fd 3 into fd 2
exec 2<&3
echo "EE oops!" >&2

Upvotes: 1

Related Questions