【问题标题】:Bash shell script not getting connect to MongoDB even if status is active即使状态处于活动状态,Bash shell 脚本也无法连接到 MongoDB
【发布时间】:2021-05-19 10:56:57
【问题描述】:

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

#!/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 &lt;&lt;EOF section时,它会返回

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 的状态是活动的,它仍然会给出这个错误。然而,如果 MongoDB 已经安装,它会成功执行整个脚本并创建数据库和集合。请帮忙。

【问题讨论】:

  • 无意冒犯,但那里有一些非常混乱的 shell 脚本。你希望kill -0 "$$" || exit 做什么?
  • 我遵循了一些教程。现在,我尝试不使用kill -0 "$$" || exit。还是一样的问题
  • kill 不是你的问题,但老实说我无法想象它应该做什么。据我所知,它基本上什么都不做:当父进程存在时,kill 成功,它可能会这样做,所以这就是它的结束。 (kill -0 并没有真正发送信号,它只是检查进程是否处于活动状态。)

标签: mongodb bash shell ubuntu-18.04


【解决方案1】:

您的脚本有许多奇怪的地方,无论当前的问题如何,都应该纠正它们。

  • kill -0 "$$" || exit 0 很奇怪,可能没有任何用处。我在这种情况下你可能根本不应该做任何事情,因为脚本的目的似乎是在组件丢失时安装它,然后继续进入mongodb_status= ...部分。
  • 由于这里的所有命令基本上都是特权命令,因此如果整个脚本没有以特权运行,那么提前中止会更有意义。

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

您的脚本的直接问题似乎是服务器需要一段时间才能开始侦听您为其配置的端口。我对 Mongo 的了解还不够,无法告诉您如何正确地等待它告诉您何时“真正”启动,但添加 sleep 是一种常见的(尽管很粗糙)的解决方法。另一种是检查日志文件,寻找监听事件。

#!/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

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

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

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 命令周围添加一个重试循环。

【讨论】:

  • 还将第二个sn-p添加到stackoverflow.com/a/67635646/874188
  • 感谢您更正我的代码。我试过你的脚本。安装 MongoDB 后,没有连接,mongo &lt;&lt;EOF 部分没有执行。同样的问题。
  • 我不知道,我实际上设置了一个 Docker 容器来测试它,它对我有用。但是已经一个星期了,我把它报废了,所以我没有简单的方法回去检查。可能你的代码需要一些额外的东西才能做任何事情;再次尝试创建minimal reproducible example
  • 好的,谢谢!
  • grep -qgrep -m 1 的作用相同,只是您可以看到它在做什么(一旦代码实际工作,您就不需要这样做了)。
猜你喜欢
  • 2021-05-23
  • 1970-01-01
  • 1970-01-01
  • 2021-10-19
  • 1970-01-01
  • 1970-01-01
  • 2012-01-03
  • 2021-09-13
  • 2013-08-27
相关资源
最近更新 更多