重启后等待MongoDB准备好的正确方法是什么?

时间:2014-10-25 02:58:52

标签: javascript bash mongodb

我有一个失败的bash脚本。检查后,似乎失败的原因是MongoDB在重新启动后立即被访问。

例如,运行:

mongo --eval "db.version()"

给出预期的输出:

  

MongoDB shell版本:2.4.9
  连接到:测试
  2.4.9

跑步时

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

产生以下输出,强调我的:

  

mongodb停止/等待
  mongodb启动/运行,过程1466
  MongoDB shell版本:2.4.9
  连接到:测试
  星期六10月25日02:52:29.736 错误:无法连接到服务器127.0.0.1:27017 在src / mongo / shell / mongo.js:145
  异常:连接失败

因为服务器尚未就绪。

在MongoDB实际准备好之前,在执行bash脚本期间等待的正确方法是什么?

  • service mongodb status不是解决方案,因为它报告服务的状态,而不是数据库本身。

  • 反复执行nc -z localhost 27017直到退出代码变为0才有效,但我不确定是否存在缺陷(以某种方式运行无限循环?)

4 个答案:

答案 0 :(得分:7)

启动mongo解释器而不连接任何db:

mongo --nodb

从那里,在mongo解释器中你可以执行:

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);

使用上面的2,您可以将后面的部分放在Script.js之类的文件中,然后执行:

mongo --nodb Script.js
编辑:在那里,完全忘记了你真正想要的是版本。为你修好了。

答案 1 :(得分:4)

建立在@Magthitus'回答,我已经添加了超时和可配置的连接字符串。

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");

您可以这样称呼它:

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

该脚本只需要host:port来测试连接,因此MONGO_URL="mongo://localhost"足以测试连接。

答案 2 :(得分:3)

不是在脚本中修复它,更好的选择(至少在我的场景中)是在mongo init script / upstart unit / systemd服务中修复它。

对于systemd:

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

答案 3 :(得分:0)

@Arseni 如果您只想返回验证和最小消息,请使用 quit() 并丢弃标准错误和输出消息。

警告 - 您可能想要设置一个超时时间 - 如果 mongo 没有出现或存在网络问题怎么办。

while true
 do

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

 done