如何检查mongodb是否已启动并准备接受来自bash脚本的连接?

Sil*_*ser 10 bash mongodb

我有一个bash shell脚本,它在尝试mongorestore之前做了很多东西.

我想确保不仅mongodb已启动,而且在尝试恢复之前它也已准备好接受连接.

现在,我所看到的是,mongo进程已启动,但在准备接受连接之前,需要45秒以上的时间进行初始设置(设置日志文件等).理想情况下,我想继续在循环中测试连接,只有当我能够连接时,我才想运行mongorestore.

有人可以告诉我如何在bash中执行此操作或指向正确的方向吗?

非常感谢!

--su

tha*_*guy 20

要像你建议的那样在循环中测试连接,

until nc -z localhost 27017
do
    sleep 1
done
Run Code Online (Sandbox Code Playgroud)

  • 反馈不好:"它不起作用".很好的反馈:"我逐字尝试了命令,它只是永远等待.我检查了stdout/stderr并继续打印`bash:nc:command not found`.我怎么解决这个问题呢?" 或者"我试过这个,它会永远等待.但是,数据库已启动并接受连接,并且netstat显示它正在侦听:`tcp 0 192.168.1.17:27017 0.0.0.0:*LISTEN`.问题是什么?" (在这些情况下,您将分别安装netcat或通过lan ip而不是localhost进行连接) (8认同)

Tom*_*Tom 8

我最近遇到了同样的问题.我决定配置mongod将其所有输出记录到日志文件,然后在循环中等待检查​​日志文件,直到我们看到一些表明mongod准备好的输出.

这是我们需要等待的示例日志文件输出行:

Tue Dec  3 14:25:28.217 [initandlisten] waiting for connections on port 27017
Run Code Online (Sandbox Code Playgroud)

这是我提出的bash脚本:

#!/bin/bash

# Initialize a mongo data folder and logfile
mkdir -p /data/db
touch /var/log/mongodb.log

# Start mongodb with logging
# --logpath    Without this mongod will output all log information to the standard output.
# --logappend  Ensure mongod appends new entries to the end of the logfile. We create it first so that the below tail always finds something
/usr/bin/mongod  --quiet --logpath /var/log/mongodb.log --logappend &

# Wait until mongo logs that it's ready (or timeout after 60s)
COUNTER=0
grep -q 'waiting for connections on port' /var/log/mongodb.log
while [[ $? -ne 0 && $COUNTER -lt 60 ]] ; do
    sleep 2
    let COUNTER+=2
    echo "Waiting for mongo to initialize... ($COUNTER seconds so far)"
    grep -q 'waiting for connections on port' /var/log/mongodb.log
done

# Now we know mongo is ready and can continue with other commands
...

请注意,脚本不会永远等待,它会在60秒后超时 - 根据您的使用情况,您可能会也可能不会想要.

  • 但是你必须重置mongo日志才能工作. (3认同)

Bjö*_*örn 8

使用MongoDB工具的解决方案.在docker容器中有用或类似于您不想安装的地方nc.

until mongo --eval "print(\"waited for connection\")"
  do
    sleep 60
  done
Run Code Online (Sandbox Code Playgroud)

根据其他人的答案.


nid*_*kil 6

在创建用户之前,我需要在 Docker 中运行的 Mongo 进行初始化。我结合了汤姆和比约恩的答案。这是我正在使用的脚本:

#!/bin/bash

# Wait until Mongo is ready to accept connections, exit if this does not happen within 30 seconds
COUNTER=0
until mongo --host ${MONGO_HOST} --eval "printjson(db.serverStatus())"
do
  sleep 1
  COUNTER=$((COUNTER+1))
  if [[ ${COUNTER} -eq 30 ]]; then
    echo "MongoDB did not initialize within 30 seconds, exiting"
    exit 2
  fi
  echo "Waiting for MongoDB to initialize... ${COUNTER}/30"
done

# Connect to the MongoDB and execute the create users script
mongo ${FWRD_API_DB} /root/create-user.js --host ${MONGO_HOST} -u ${MONGO_ROOT_USER} -p ${MONGO_ROOT_PASSWORD} --authenticationDatabase admin
Run Code Online (Sandbox Code Playgroud)


Dan*_*515 5

虽然 Tom 的答案在大多数情况下都能很好地工作,但如果您使用-e标志运行脚本,它可能会失败。我的意思是你set -e在最顶端运行你的脚本。为什么?因为 Tom 的回答依赖于前一个命令的退出状态,在这种情况下grep -q,如果找不到所需的字符串,它将失败,因此整个脚本将失败。该-e标志的文件提供了有关如何避免此问题的一个线索:

如果失败的命令是紧跟在 while 或 until 关键字之后的命令列表的一部分、if 语句中测试的一部分、在 && 或 || 中执行的任何命令的一部分,则 shell 不会退出 列表除了最后一个 && 或 || 之后的命令,管道中除最后一个之外的任何命令,或者如果命令的返回状态正在用 ! 反转。

因此,一种解决方案是使 grep 命令成为 while 条件的一部分。但是,由于他正在使用--logappend选项运行 mongodb,因此搜索字符串可能会作为上次运行的结果出现。我将另一个人的答案与汤姆的答案结合起来,效果非常好:

# Wait until mongo logs that it's ready (or timeout after 60s)
COUNTER=0
while !(nc -z localhost 27017) && [[ $COUNTER -lt 60 ]] ; do
    sleep 2
    let COUNTER+=2
    echo "Waiting for mongo to initialize... ($COUNTER seconds so far)"
done
Run Code Online (Sandbox Code Playgroud)

我发现使用 tomcat 是最好的解决方案,因为它实际上测试是否有东西在听。