【问题标题】:Bash command output string comparison and using IF ELSE conditionBash 命令输出字符串比较和使用 IF ELSE 条件
【发布时间】:2019-06-08 06:18:20
【问题描述】:

如何比较 bash 命令输出并使用 IF ELSE 块做某事。

我正在尝试在 CMD 变量中捕获 bash 命令输出,如果该变量为空/零,则输出缺少二进制/功能。很基本。

在下面的代码中,第二个 if else

# Check if the CPU supports KVM
cmd=$(grep -Eiw 'vmx|svm' /proc/cpuinfo)
if [[ $cmd -ne 0 ]];then 
    echo "CPU on this machine does not support KVM. Check documentation please"
fi



#!/bin/bash

# Check if KVM kernel modules are installed.
cmd=$(lsmod | awk '{print $1}' | grep -Eiw 'kvm\|kvm_intel\|kvm_amd')
if [[ $cmd -ne 0 ]];then 
    echo "KVM kernel modules kvm or kvm_[intel|amd] missing. Use modprobe to load them please"
fi

# Check if the CPU supports KVM
cmd=$(grep -Eiw 'vmx|svm' /proc/cpuinfo)
if [[ $cmd -ne 0 ]];then 
    echo "CPU on this machine does not support KVM. Check documentation please"
fi

脚本不只是检查条件,而是打印命令输出(/proc/cpuinfo),我只希望它打印回显行而不是命令输出。

【问题讨论】:

  • 您是要检查grep 返回 还是它输出stdout 的内容?这是两个不同的东西。cmd=$(grep ...) 捕获输出。
  • 我正在尝试 grep 一个字符串 ...如果该字符串存在,则执行某些操作,如果 grep 输出中不存在该字符串,请执行其他操作。
  • 我知道您正在尝试 grep 字符串。我试图了解您试图从 grep 中检查的结果。根据grep 的手册页,通常退出状态如果选择了一行,则为 0,如果没有选择行,则为 1,如果发生错误,则为 2。如果您正在检查退出状态,那么您就走错了路。如果您想要退出状态,请在执行grep 后立即检查$?。如果有匹配,它将具有值 0。您不会使用cmd=$(grep ...) 获得退出状态。
  • 我没有检查退出代码。我正在尝试的是以下 cmd=$(grep -Eiw 'vmx|svm' /proc/cpuinfo)
  • 如果您不尝试检查退出代码,那么您为什么要检查grep 的结果与0grep -Eiw 'vmx|svm'... 的结果将是一行或多行包含vmxsvm,或者根本没有行。在完全没有行的情况下,grep 不会输出 0。

标签: bash


【解决方案1】:

你让这变得比需要的更困难。您只需要使用复合命令来(1)检查vmxsvm扩展是否存在于/proc/cpuinfo中,以及(2)检查kvmkvm_intel是否存在通过检查/proc/modules 加载模块。使用复合命令只需要两个调用:

#!/bin/bash

grep -wq 'vmx\|svm' /proc/cpuinfo || {   ## check CPU support
    printf "error: CPU does not support vmx or svm extensions.\n" >&2
    exit 1
}

grep -q '^kvm' /proc/modules || {        ## check modules loaded
    printf "error: CPU supports KVM, but kvm modules not loaded.\n" >&2
    exit 1
}

printf "CPU supports KVM and modules present.\n"

使用/输出示例

$ bash ~/scr/utl/kvmsupport.sh
CPU supports KVM and modules present.

您可以通过多种方式做到这一点,但通常越简单,出错的机会就越少。

【讨论】:

    【解决方案2】:

    你应该检查命令退出状态,而不是它的输出。

    #!/bin/bash
    
    # Check if KVM kernel modules are installed.
    if ! lsmod | awk '{print $1}' | grep -q -Eiw 'kvm|kvm_intel|kvm_amd'; then
        echo "KVM kernel modules kvm or kvm_[intel|amd] missing. Use modprobe to load them please"
    fi
    
    # Check if the CPU supports KVM
    if ! grep -q -Eiw 'vmx|svm' /proc/cpuinfo; then
        echo "CPU on this machine does not support KVM. Check documentation please"
    fi
    

    #!/bin/bash
    
    # Check if KVM kernel modules are installed.
    lsmod | awk '{print $1}' | grep -q -Eiw 'kvm\|kvm_intel\|kvm_amd'
    ret=$?
    if ((ret != 0)); then
        echo "KVM kernel modules kvm or kvm_[intel|amd] missing. Use modprobe to load them please"
    fi
    
    # Check if the CPU supports KVM
    grep -q -Eiw 'vmx|svm' /proc/cpuinfo
    ret=$?
    if ((ret != 0)); then
        echo "CPU on this machine does not support KVM. Check documentation please"
    fi
    

    还要确定是使用grep 'vmx\|svm' 还是grep -E 'vmx|svm'。在 -E 中转义 \| 会将 | 解析为文字字符。这里bashfaq How can I store the return value and/or output of a command in a variable? 是一个很好的 bash 介绍。

    grep -Eiw 看起来也有点奇怪。您真的在寻找名为KvM_InTeLkVM_INteLkVm_InTeL 的模块吗?只有一个模块名称,它是小写的 - kvmkvm_intelkvm_amd。同样使用 -w 是无关紧要的 - lsmod | awk '{print $1}' 输出已经是每行一个。我会选择grep 'kvm\|kvm_intel\|kvm_amd'

    【讨论】:

      【解决方案3】:

      感谢您的回答。

      你们中的许多人建议使用退出代码,这可能是答案,但我专门检查存储在变量中的输出结果是空字符串还是非空字符串,并且 [[ ]] 测试条件不应输出到 STD -OUT,只做比较,不向终端输出任何东西。

      其次,我不想使用 -q,因为它以零状态退出,不仅适用于找到的任何匹配项,也适用于遇到的错误。

      第三,我没有使用 egrep,因为它是非标准且已弃用 [Ref:http://pubs.opengroup.org/onlinepubs/9699919799/utilities/grep.html]

      最后,使用 -i 和 -w 是多余的,因为模块将是小写的,而 awk 的作用与 -w [同意] 相同,但只是想避免假设它总是小写。

      我的解决方案: cmd=$(grep -Eiw 'vmx|svm' /proc/cpuinfo) [[ -z "$cmd" ]] && echo "error: :CPU 不支持 KVM。检查文档。" && 退出 1

      -z 不会将返回字符串输出到终端,只是告诉字符串是空的还是非空的。

      【讨论】:

        【解决方案4】:

        当且仅当某些模式匹配时,获得零退出代码的标准方法是grep --quiet PATTERN(如果您没有 GNU Grep,则为 -q)。如果grep 是管道中的last 命令,或者您使用set -o pipefail 获取管道中的第一个非零退出代码作为整个管道。

        所以在你的情况下,它只是:

        if lsmod | awk '{print $1}' | grep -Eiw 'kvm\|kvm_intel\|kvm_amd'
        then
            …
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2019-08-20
          • 2018-07-10
          • 1970-01-01
          • 2021-03-09
          • 2011-12-12
          • 2014-09-12
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多