【问题标题】:What is the correct way to wait until MongoDB is ready after restart?重启后等待MongoDB准备就绪的正确方法是什么?
【发布时间】:2014-10-25 02:58:51
【问题描述】:

我有一个失败的 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 错误:无法在 src/mongo/shell/mongo.js:145 连接到服务器 127.0.0.1:27017
异常:连接失败

因为服务器还没有准备好。

在执行 bash 脚本期间等待 MongoDB 实际就绪的正确方法是什么?

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

  • 重复执行 nc -z localhost 27017 直到其退出代码变为 0 将起作用,但我不确定是否没有缺点(以某种方式运行无限循环?)

【问题讨论】:

    标签: javascript bash mongodb


    【解决方案1】:

    在不连接任何数据库的情况下启动 mongo 解释器:

    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
    

    编辑:那里,完全忘记了你真正想要的是版本。为你解决了这个问题。

    【讨论】:

      【解决方案2】:

      基于@Magnitus 的回答,我添加了一个超时和可配置的连接字符串。

      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"就足够测试连接了。

      【讨论】:

      • 注意:除非您使用 --nodb 标志运行脚本,否则这将不起作用 - 如果没有它,如果数据库已关闭,该命令只会阻塞连接错误并输出错误代码 1 .
      【解决方案3】:

      与其在脚本中修复这个问题,更好的选择(至少对于我的场景)是在 mongo init 脚本/upstart 单元/systemd 服务中修复它。

      对于系统:

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

      【讨论】:

        【解决方案4】:

        @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
         
        

        【讨论】:

          猜你喜欢
          • 2018-12-16
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2014-03-29
          • 1970-01-01
          • 2022-10-23
          • 2013-03-24
          • 1970-01-01
          相关资源
          最近更新 更多