我有一个bash shell脚本,它在尝试mongorestore
之前会做很多事情。
我想确保不仅MongoDB已启动,而且在尝试恢复之前它也已准备好接受连接。
现在,我看到的是,mongo进程已启动,但在准备好接受连接之前,需要45秒以上的时间进行初始设置(设置日志文件等)。理想情况下,我想继续在循环中测试连接,只有当我能够连接时,我才想运行mongorestore
。
有人可以告诉我如何在Bash中执行此操作或指向正确的方向吗?
答案 0 :(得分:19)
要像你建议的那样在循环中测试连接,
until nc -z localhost 27017
do
sleep 1
done
答案 1 :(得分:7)
我最近遇到了同样的问题。我决定配置 mongod 将所有输出记录到日志文件中,然后在循环中等待检查日志文件,直到我们看到一些表明mongod准备就绪的输出。
这是我们需要等待的示例日志文件输出行:
Tue Dec 3 14:25:28.217 [initandlisten] waiting for connections on port 27017
这是我提出的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秒后超时 - 根据您的使用情况,您可能会也可能不会这样。
答案 2 :(得分:7)
使用MongoDB工具的解决方案。在docker容器或类似的地方很有用,你不想安装nc
。
until mongo --eval "print(\"waited for connection\")"
do
sleep 60
done
基于其他人的答案。
答案 3 :(得分:4)
虽然Tom的答案在大多数情况下都能很好地运行,但如果您使用-e
标志运行脚本,它可能会失败。我的意思是你在顶部用set -e
运行你的脚本。为什么?因为Tom的答案依赖于前一个命令的退出状态,在这种情况下grep -q
如果找不到所需的字符串将失败,因此整个脚本将失败。 -e
标记文档提供了如何避免此问题的线索:
如果失败的命令是shell的一部分,则shell不会退出 命令列表紧跟一段时间或直到关键字,部分 if语句中的测试,是&&amp ;;中执行的任何命令的一部分。要么 ||列表除了最后一个&&之后的命令或||,任何命令 在管道中但是最后一个,或者命令的返回状态是什么 倒了!。
因此,一种解决方案是使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
我发现使用tomcat是最好的解决方案,因为它实际上会测试是否有什么东西在监听。
答案 4 :(得分:0)
在创建用户之前,我需要在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
答案 5 :(得分:0)
给我一个docker_id
可以像这样读取docker logs
:
until [ $(docker logs --tail all $docker_id | grep "waiting for connections on port" | wc -l) -gt 0 ]; do
printf '.'
sleep 1
done
然后继续执行任何依赖于mongo的任务。