即使状态处于活动状态,Bash shell 脚本也无法连接到 MongoDB [英] Bash shell script not getting connect to MongoDB even if status is active

查看:41
本文介绍了即使状态处于活动状态,Bash shell 脚本也无法连接到 MongoDB的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

使用 Ubuntu 18.04.我有以下 bash 脚本来安装和运行 MongoDB.IT 检查是否安装了 MongoDB 并运行一些 mongo shell 命令:

Using Ubuntu 18.04. I have the following bash script to install and run the MongoDB. IT checks if MongoDB is installed or not and run some mongo shell commands:

#!/bin/bash

if [ -f /usr/bin/mongod ]; then
          echo "MongoDB is installed on your machine."
            kill -0 "$$" || exit
else
            password=password
            echo "********************* MongoDB 4.0 INSTALL **************************"
            echo "MongoDB is is not installed."

            echo "******************************************************************"
            echo $password | sudo apt-key adv --keyserver hkp://keyserver.ubuntu.com:80 --recv 68818C72E52529D4

            echo $password | sudo bash -c "echo deb http://repo.mongodb.org/apt/ubuntu bionic/mongodb-org/4.0 multiverse" | sudo tee /etc/apt/sources.list.d/mongodb-org-4.0.list
            sudo bash -c "apt update && apt upgrade -y"
            sudo bash -c "apt-get install -y mongodb-org"

            sudo bash -c "apt update && apt upgrade -y"
            echo 'y' | sudo bash -c "apt autoremove && apt clean"

            sudo bash -c "mkdir /data /data/db"

            sudo bash -c "systemctl enable mongod"  #enables Mongo on system startup
            sudo bash -c "service mongod start"
            sudo bash -c "service mongod restart"

            kill -0 "$$" || exit

            echo "********************* MongoDB Create DB and Collection **************************"
fi
mongod_status=`systemctl is-active mongod`
echo "${mongod_status}"

if [[ "${mongod_status}" == "active" ]]
then
            echo "MongoDB is already running."
    else
            echo "MongoDB is not running"
            rm /var/lib/mongodb/mongod.lock
            sudo bash -c "service mongod start"
    fi
mongo <<EOF
        use fragment
        db.createCollection("fragmenthash");
EOF

如果我的系统没有安装 MongoDB,这个脚本会安装并启动它.然后它检查状态,它是活动的".但是当它执行mongo <<EOF section时,它返回

If my system is not installed with MongoDB, this script installs and start it. Then it checks the status, which is "active". But then when it executes mongo <<EOF section, it returns

connecting to: mongodb://127.0.0.1:27017/?gssapiServiceName=mongodb
2021-05-19T10:06:01.134+0000 E QUERY    [js] Error: couldn't connect to server 127.0.0.1:27017, connection attempt failed: SocketException: Error connecting to 127.0.0.1:27017 :: caused by :: Connection refused :
connect@src/mongo/shell/mongo.js:356:17
@(connect):2:6
exception: connect failed

即使 MongoDB 的状态为 Active 仍然会出现此错误.而如果 MongoDB 已经安装,它会通过创建数据库和集合成功执行整个脚本.请帮忙.

Even if the status of MongoDB is Active still it gives this error. Whereas, if MongoDB is already installed, it executes the whole script successfully with creating DB and collection. Please help.

推荐答案

你的脚本有很多奇怪的地方,不管眼前的问题如何,都应该理顺.

Your script has a number of oddities which should probably be straightened out regardless of the immediate problem.

  • kill -0 "$$";||exit 0 很奇怪,可能没有任何用处.我猜测在这种情况下你可能什么都不做,因为脚本的目的似乎是安装缺少的组件,然后进入mongodb_status=... 部分.
  • 由于这里的所有命令基本上都是特权命令,如果整个脚本没有以特权运行,那么提前中止会更有意义.
  • kill -0 "$$" || exit 0 is weird and probably does nothing useful. I guess you probably simply should do nothing in this case, as the purpose of the script seems to be to install the component if it's missing, and then proceed into the mongodb_status= ... part.
  • As basically all the commands here are privileged, it would make more sense to just abort up front if the entire script is not running with privileges.

在风格上,所有看起来像 sudo bash -c 'singlecommand' 的东西都应该只是 sudo singlecommand;但是通过建议的重构,您根本不需要这些.

Stylistically, everything which looks like sudo bash -c 'singlecommand' should be just sudo singlecommand; but with the proposed refactoring, you don't need these at all.

您的脚本的直接问题似乎是服务器开始侦听您为其配置的端口需要一段时间.我对 Mongo 知之甚少,无法告诉您如何正确等待它真正"启动时告诉您.但是添加 sleep 是一种常见的(虽然粗略)的解决方法.另一个是检查日志文件,寻找监听事件.

The immediate problem with your script seems to be that it takes a while for the server to start listening on the port you configured it for. I don't know enough about Mongo to tell you how to properly wait for it to tell you when it's up "for real" but adding a sleep is a common (albeit crude) workaround. Another is to examine the log file, looking for the listening event.

#!/bin/bash

# Test for privileged access
test -w / ||
{ echo "$0: need to run privileged; aborting" >&2; exit 127; }

startit () {
    local log=/var/log/mongodb/mongod.log
    service mongod start
    while true; do
        test -e "$log" && break
        sleep 1
    done
    grep -q 'port: 27017' "$log" ||
    tail -0f "$log" |
    grep -q 'port: 27017'
}

if [ -f /usr/bin/mongod ]; then
    # Send diagnostic messages to standard error
    echo "$0: MongoDB is installed on your machine." >&2
else
    # Reduce eyesore
    echo "$0: MongoDB is not installed; proceed with 4.0 install" >&2
    apt-key adv --keyserver hkp://keyserver.ubuntu.com:80 --recv 68818C72E52529D4
    echo "deb http://repo.mongodb.org/apt/ubuntu bionic/mongodb-org/4.0 multiverse" >/etc/apt/sources.list.d/mongodb-org-4.0.list
    apt update && apt upgrade -y
    apt-get install -y mongodb-org
    # not necessary or useful to do a second time
    # apt update && apt upgrade -y
    apt -y autoremove && apt clean
    mkdir -p /data/db
    systemctl enable mongod
    startit
    # service mongod restart  # is this really useful and necessary?
fi
echo "$0: database initialization" >&2

# Prefer modern command substitution syntax
mongod_status=$(systemctl is-active mongod)
echo "$mongod_status" >&2

if [[ "${mongod_status}" == "active" ]]
then
    echo "$0: MongoDB is already running." >&2
else
    echo "$0: MongoDB is not running" >&2
    rm -f /var/lib/mongodb/mongod.lock
    startit
fi

mongo <<EOF
        use fragment
        db.createCollection("fragmenthash");
EOF

我对 startit 函数并不完全满意——起初它失败了,因为我试图在它不存在时打开日志文件,然后它失败了,因为在一秒钟睡眠后,日志文件已包含启动消息.现在,如果附加日志文件并且旧日志包含来自前一个会话的启动消息,它仍然可能失败.但至少这应该能让你朝着正确的方向开始,我希望.

I'm not entirely happy with the startit function -- at first it failed because I tried to open the log file when it did not yet exist, then it failed because the new lines in the log file already contained the startup message after the one-second sleep. Now it could still fail if the log file is being appended and the old logs contain the startup message from a previous session. But at least this should get you started in the right direction, I hope.

这是一个重构,可能更健壮......

Here's a refactoring which might be more robust ...

startit () {
    local log=/var/log/mongodb/mongod.log
    sudo -u mongodb touch "$log"
    service mongod start &
    local launcher=$!
    tail -0f "$log" |
    grep -q 'port: 27017'
    wait "$launcher"
    sleep 1
}

最后的sleep有点绝望;在它记录启动后似乎需要一点时间,直到它正确启动并收听;和/或在最后的 mongo 命令周围添加一个重试循环.

The final sleep is a bit of an act of desperation; it seems to take a jiffy after it logs the startup until it's properly up and listening; and/or maybe add a retry loop around the final mongo command.

这篇关于即使状态处于活动状态,Bash shell 脚本也无法连接到 MongoDB的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆