Bash 脚本 if/then 具有多个条件

Bash script if/then with multiple conditions

我只想在 DNS 状态为:"NXDOMAIN" 或 "SERVFAIL" 且具有 "CNAME".

时打印主机名和 CNAME

条件:

dig @8.8.8.8 -t A ${hstnm} | grep -q 'NXDOMAIN'
dig @8.8.8.8 -t A ${hstnm} | grep -q 'SERVFAIL'
dig @8.8.8.8 -t CNAME $hstnm +short >/dev/null

所以我在下面写了 bash 脚本但是它不起作用,非常感谢任何帮助,谢谢。

for hstnm in $(cat /path/file.txt)
do
if dig @8.8.8.8 -t A ${hstnm} | grep -q 'NXDOMAIN' || dig @8.8.8.8 -t A ${hstnm} | grep -q 'SERVFAIL' && dig @8.8.8.8 -t CNAME $hstnm +short >/dev/null ]]
then
echo -n -e "\e[92mNXDOMAIN: \e[0m${hstnm} "
echo -n -e "\e[93mCNAME: \e[0m"; dig @8.8.8.8 -t CNAME $hstnm +short
echo
fi
done

好的,让我们标记您的条件:

  • A 是 dig @8.8.8.8 -t A "$hstnm" | grep -q 'NXDOMAIN'
  • B 是 dig @8.8.8.8 -t A "$hstnm" | grep -q 'SERVFAIL'
  • C 是 dig @8.8.8.8 -t CNAME "$hstnm" +short >/dev/null

现在,用这些名字,用算法语言告诉我们你想要什么测试。
另外,我们需要知道您正在使用的 shell (BASh?Korn?Almiquish?Z?)
根据这些参数,我们可能会提供更好的指示。例如

#!/bin/bash

for hstnm in $(cat /path/file.txt)
do
if ( dig @8.8.8.8 -t A "$hstnm" | grep -q 'NXDOMAIN' ) || ( dig @8.8.8.8 -t A "$hstnm" | grep -q 'SERVFAIL' ) && ( dig @8.8.8.8 -t CNAME "$hstnm" +short >/dev/null )
then
echo -n -e "\e[92mNXDOMAIN: \e[0m${hstnm} "
echo -n -e "\e[93mCNAME: \e[0m"; dig @8.8.8.8 -t CNAME "$hstnm" +short
echo
fi
done

假设"A or B then C" ...


edit-2020-08-04 好的,您要实现的目标是 "IF (either "A" 或 "B" 为真)和("C" 为真)然后"
第一部分 "either "A" or "B" is true" 应该翻译成 A || B

if ( dig @8.8.8.8 -t A "$hstnm" | grep -q 'NXDOMAIN' ) || ( dig @8.8.8.8 -t A "$hstnm" | grep -q 'SERVFAIL' )
then
#foo
fi

首先,我将 "A" 和 "B" 分组在括号中......或大括号。如果我不这样做,我会以一种有点令人惊讶的方式改变含义: dig @8.8.8.8 -t A "$hstnm" | grep -q 'NXDOMAIN' || dig @8.8.8.8 -t A "$hstnm" | grep -q 'SERVFAIL' 问 shell 到

  • 挖掘 google 主机地址,并检查是否有 "no such domain" 答案。
  • 当检查不成功时(双管道),挖掘 google 相同的主机地址并检查是否有 "issue reaching the domain name server" 答案。
  • 但是当第一次检查没有失败时,就没有其他挖掘(很好),但是一些 shells 将继续并将先前的输出通过管道传递给 grep' 命令(我没有检查我的 bash 的行为,但依赖这些东西是不好的)...什么会导致大失败(因为我们来自静默检查,所以管道中没有输入第二次消费)

所以你明白为什么这里有括号了。但要注意:与 bourne 兼容的 shell 没有像许多编程语言那样用于对逻辑操作进行分组的括号。事实上,我们没有使用布尔转换,而只是 shell 的能力,可以根据前一个命令的成功或失败来调用命令(它不像其他地方看到的那样真假系统,即使在使用命令如 test) 尽管有相似之处,括号在子 shell 中分组命令(如果您不想使用子 shell 并使一些变量受益,请使用大括号-down) 处理该组时,它将作为一个块失败或成功,并具有组中最后一个命令 运行 的 return 代码。

现在,我们可能会考虑使用分组的分组来实现我们的目标。

if { ( dig @8.8.8.8 -t A "$hstnm" | grep -q 'NXDOMAIN' ) || ( dig @8.8.8.8 -t A "$hstnm" | grep -q 'SERVFAIL' ) } && ( dig @8.8.8.8 -t CNAME "$hstnm" +short >/dev/null )
then
#foo
fi

坦率地说,我不知道 shell 是如何支持嵌套分组的,如果不是被迫的话,我永远不会尝试找到答案(你知道,当你继承了你拥有的脚本时修复...)我发现很难回读,因此很难维护。我更喜欢走另一条路:

if ( dig @8.8.8.8 -t A "$hstnm" | grep -q 'NXDOMAIN' ) || ( dig @8.8.8.8 -t A "$hstnm" | grep -q 'SERVFAIL' )
then 
  if dig @8.8.8.8 -t CNAME "$hstnm" +short >/dev/null
  then
  #foo
  fi
fi

待后续。

这是你的 post 目前所说的(简体):

if A || B && C ]]
then
  ...
fi

只需删除尾随 ]]

您不需要添加任何分组,因为与许多语言不同,A || B && C 在这种情况下 Bash 等同于 (A || B) && C