最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - What is the correct way to wait until MongoDB is ready after restart? - Stack Overflow

programmeradmin2浏览0评论

I have a bash script which fails. After inspection, it appears that the failure is due to the fact that MongoDB is accessed immediately after being restarted.

For example, running:

mongo --eval "db.version()"

gives the expected output:

MongoDB shell version: 2.4.9
connecting to: test
2.4.9

while running:

service mongodb restart; mongo --eval "db.version()"

produces the following output, emphasis mine:

mongodb stop/waiting
mongodb start/running, process 1466
MongoDB shell version: 2.4.9
connecting to: test
Sat Oct 25 02:52:29.736 Error: couldn't connect to server 127.0.0.1:27017 at src/mongo/shell/mongo.js:145
exception: connect failed

because the server is not ready yet.

What is the correct way to wait during the execution of the bash script until MongoDB is actually ready?

  • service mongodb status is not a solution, because it reports the status of the service, and not the database itself.

  • Doing nc -z localhost 27017 repeatedly until its exit code becomes 0 will work, but I'm not sure if there are no drawbacks (running somehow an infinite loop?)

I have a bash script which fails. After inspection, it appears that the failure is due to the fact that MongoDB is accessed immediately after being restarted.

For example, running:

mongo --eval "db.version()"

gives the expected output:

MongoDB shell version: 2.4.9
connecting to: test
2.4.9

while running:

service mongodb restart; mongo --eval "db.version()"

produces the following output, emphasis mine:

mongodb stop/waiting
mongodb start/running, process 1466
MongoDB shell version: 2.4.9
connecting to: test
Sat Oct 25 02:52:29.736 Error: couldn't connect to server 127.0.0.1:27017 at src/mongo/shell/mongo.js:145
exception: connect failed

because the server is not ready yet.

What is the correct way to wait during the execution of the bash script until MongoDB is actually ready?

  • service mongodb status is not a solution, because it reports the status of the service, and not the database itself.

  • Doing nc -z localhost 27017 repeatedly until its exit code becomes 0 will work, but I'm not sure if there are no drawbacks (running somehow an infinite loop?)

Share Improve this question edited Nov 25, 2015 at 16:18 Mikey 2,95134 silver badges37 bronze badges asked Oct 25, 2014 at 2:58 Arseni MourzenkoArseni Mourzenko 52.3k35 gold badges118 silver badges210 bronze badges
Add a comment  | 

4 Answers 4

Reset to default 8

To start the mongo interpreter without connection to any db:

mongo --nodb

From there, inside the mongo interpreter you can execute:

var conn;
try
{
    conn = new Mongo("localhost:27017");
}
catch(Error)
{
    //print(Error);
}
while(conn===undefined)
{
    try
    {
        conn = new Mongo("localhost:27017");
    }
    catch(Error)
    {
        //print(Error);
    }
    sleep(100);
}
DB = conn.getDB("test");
Result = DB.runCommand('buildInfo');
print(Result.version);

With the 2 above, you can put the later part in a file like Script.js and then do:

mongo --nodb Script.js

EDIT: There, totally forgot that what you really wanted was the version. Fixed that for you.

Building upon @Magnitus' answer, I've added a timeout and configurable connection string.

var conn;
var interval = 100;   // 100 Milliseconds polling
var timeout  = 10000; // 10 Seconds timeout
var startTime = new Date();
connectionUrl = connectionUrl.split('/')[2];

if (connectionUrl.indexOf('@') !== -1) {
  // Has auth (doesn't need auth for test connection)
  connectionUrl = connectionUrl.split('@')[1];
}

while(conn === undefined) {
  try {
    var elapsed = (new Date() - startTime);
    print("Attempting to connect to " + connectionUrl + " elapsed: " + elapsed + "ms");
    conn = new Mongo(connectionUrl);
  } catch(error) {
    print(error);

    if ((new Date() - startTime) >= timeout) {
      print("ERROR: Failed to establish connection within timeout (" + timeout + "ms)");
      quit(1);
    } else {
      sleep(interval);
    }
  }
}

print("MongoDB connection established in " + (new Date() - startTime) + "ms");

You can call it like so:

export MONGO_URL="mongo://<user>:<pass>@<host>:<port>/<database>"
mongo --nodb wait_for_mongo.js --eval "connectionUrl=\"$MONGO_URL\""

The script only requires the host:port to test the connection, so MONGO_URL="mongo://localhost" is enough to test the connection.

Rather than fixing this in the script, a better option (at least for my scenario) is to fix it in the mongo init script / upstart unit / systemd service.

For systemd:

ExecStartPost=/bin/sh -c 'while ! /usr/bin/mongo --eval "db.version()" > /dev/null 2>&1; do sleep 0.1; done'

@Arseni if you want just the verification and minimum message back use quit() and discard the standard error and output messages.

Caveat - you may want to put a timeout - what if mongo does not come up or there is a network issue.

while true
 do

   mongo --quiet --eval "quit()"  1>/dev/zero 2>&1  
   rc=$?    
   if [ $rc -ne 0 ] 
     then sleep 2 
   else 
     break
   fi

 done
 
发布评论

评论列表(0)

  1. 暂无评论