连续运行命令并在第一个命令以 0 退出时停止

连续运行命令并在第一个命令以 0 退出时停止

我有这 3 个命令:

  mongo cdt_prod_playground --host "mngdb-cbt-stg-01:27058" -u cdtprodplayground -p "x" --eval "db.${file%.*}.remove({})"
  mongo cdt_prod_playground --host "mngdb-cbt-stg-02:27058" -u cdtprodplayground -p "x" --eval "db.${file%.*}.remove({})" 
  mongo cdt_prod_playground --host "mngdb-cbt-stg-03:27058" -u cdtprodplayground -p "x" --eval "db.${file%.*}.remove({})"

我想运行它们并在第一个成功时停止。我想一种方法是将它们放入一个数组中,并在命令成功时跳出循环,但我该怎么做呢?

(原因是我需要这样做是因为我不知道哪个主机是副本集 PRIMARY,所以我只能暴力测试它,因为我没有运行的授权rs.status()。)

答案1

您应该在命令行中使用副本集连接字符串,而不是在所有副本集成员上尝试使用命令来确定哪一个是当前的主副本集mongo。您可以选择在连接字符串中包含用户名和密码凭据,而不是使用单独的命令行参数。

使用 MongoDB 3.6.3 shell 的示例:

mongo "mongodb://USERNAME:PASSWORD@mngdb-cbt-stg-01:27058,mngdb-cbt-stg-02:27058/DATABASE?replicaSet=cdt_prod_playground" --eval "db.${file%.*}.remove({})"

您不必在连接字符串中列出副本集的所有成员。我在上面的示例中使用了两个,因为这应该确保在三成员副本集中发现主副本(需要 2/3 的投票成员来维护主副本)。只要您replicaSet在连接字符串中包含名称并且连接字符串中至少有一个成员是健康的,驱动程序/客户端就会确定当前成员。

连接字符串 URI 格式以获得可用选项的参考。

另请注意,调用db.collection.remove({})将删除单个文档,同时保留索引定义。如果您有大量的集合数据需要删除,那么调用db.colellection.drop()并重新创建任何所需的索引会更快。

原因是我需要这样做是因为我不知道哪个主机是副本集 PRIMARY,所以我只能对其进行暴力测试,因为我没有运行 rs.status() 的授权

如果您需要以编程方式发现当前的主数据库,您可以使用isMaster命令。 MongoDB 驱动程序和客户端(如 shell)使用此命令mongo作为初始连接协商的一部分。当连接到副本集成员时,isMaster输出包括primary当前的其他详细信息副本集状态

在 MongoDB 3.6 中,该isMaster命令不需要身份验证,因为它用于提供驱动程序/客户端发现服务器和协商经过身份验证的连接所需的信息。

答案2

||IIUC,您可以使用ifmongo返回非零错误来连接行。如中所述man bash

An OR list has the form

           command1 || command2

   command2 is executed if and only if command1 returns a non-zero exit status.  The return status of AND and OR lists is the exit status of the last command executed in the list.

我这里没有mongo,但我可以发布一个例子succeeds.sh

#!/usr/bin/env sh
nonexistent-command || \
echo a || \
echo b || \
echo c    

跑步:

$ ./succeeds.sh
./succedds.sh: line 3: nonexistent-command: command not found
a

正如您所看到的,脚本停止于,a因为这是第一个成功的命令。

答案3

hostlist=(mngdb-cbt-stg-01:27058 mngdb-cbt-stg-02:27058 mngdb-cbt-stg-03:27058)
hostnum=0
set -u
/bin/false; while [[ 0 -ne $? ]]; do 
  mongo cdt_prod_playground --host "${hostlist[$hostnum]}" -u cdtprodplayground -p "x" --eval "db.${file%.*}.remove({})"
  hostnum=$((hostnum+1))
done

相关内容