Bash shell 脚本无法连接到 MongoDB 即使状态为活动

Bash shell script not getting connect to MongoDB even if status is active

使用 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 <<EOF section 时,它 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 已经安装,它会成功执行整个脚本并创建数据库和集合。请帮忙。

你的脚本有很多奇怪的地方,不管眼前的问题是什么,都应该加以纠正。

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

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

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

#!/bin/bash

# Test for privileged access
test -w / ||
{ echo "[=10=]: 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 "[=10=]: MongoDB is installed on your machine." >&2
else
    # Reduce eyesore
    echo "[=10=]: 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 "[=10=]: database initialization" >&2

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

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

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

我对 startit 功能不是很满意 -- 起初它失败了,因为我试图在它还不存在的时候打开日志文件,然后它失败了,因为日志中的新行一秒休眠后,文件中已经包含了启动消息。现在,如果正在附加日志文件并且旧日志包含来自前一个会话的启动消息,它仍然可能会失败。但至少这应该让你开始朝着正确的方向前进,我希望。

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

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有点走投无路;在记录启动后直到它正常启动并收听时似乎需要一点时间; and/or 可能会在最后的 mongo 命令周围添加一个重试循环。