Buggy B
Buggy B

Reputation: 765

Bash command output string comparison and using IF ELSE condition

How do I compare bash command output and use IF ELSE block to do something.

I am trying to capture the bash command output in CMD variable and if the variable is empty / zero, then output that the binary/feature is missing. Pretty basic.

In the below code, the second 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

Instead of just checking the condition, the script is printing the command output (/proc/cpuinfo), I just want it to print the echo line but not the command output.

Upvotes: 1

Views: 1036

Answers (4)

Buggy B
Buggy B

Reputation: 765

Thank you for your answers.

Many of you suggested using exit code which maybe the answer but I was specific about checking if the output result stored in the variable is an empty string or non-empty string and the [[ ]] test condition should not output to STD-OUT, just do a comparison without outputting anything to the terminal.

Second, I didn't want to use -q as it exits with zero status , not only for any match found but also for errors encountered.

Thirdly, I didn't use egrep as it is non-standard and deprecated [Ref:http://pubs.opengroup.org/onlinepubs/9699919799/utilities/grep.html]

Lastly, using -i and -w is redundant as the modules will be in lowercase and awk is doing the same as -w [Agreed] but just wanted to avoid assumptions esp that it will always be lowercase.

My Solution: cmd=$(grep -Eiw 'vmx|svm' /proc/cpuinfo) [[ -z "$cmd" ]] && echo "error: :CPU does not support KVM. Check documentation." && exit 1

-z does not output the return string to the terminal and just tells if the string is empty or non-empty.

Upvotes: 1

KamilCuk
KamilCuk

Reputation: 141200

You should check command exit status, not it's output.

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

or

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

Also decide if you use grep 'vmx\|svm' or grep -E 'vmx|svm'. Escaping \| in -E will parse | as literal character. Here bashfaq How can I store the return value and/or output of a command in a variable? is a good bash introduction.

Also the grep -Eiw looks a bit strange. Are you really looking for a modules named KvM_InTeL or kVM_INteL or kVm_InTeL? There is only one module name, it's lowercase - kvm, kvm_intel, kvm_amd. Also using -w is irrelevant - lsmod | awk '{print $1}' output is already one per line. I would just go with grep 'kvm\|kvm_intel\|kvm_amd'.

Upvotes: 1

David C. Rankin
David C. Rankin

Reputation: 84569

You are making this more difficult than need be. You simply need to use a compound command to (1) check whether vmx or svm extensions are present in /proc/cpuinfo, and (2) check whether the kvm or kvm_intel module is loaded by checking /proc/modules. Using a compound command two calls are all that are needed:

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

Example Use/Output

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

You can do it any number of ways, but generally the simpler you can keep it, the less opportunity for error there is.

Upvotes: 1

l0b0
l0b0

Reputation: 58858

The standard way to get a zero exit code if and only if some pattern is matched is grep --quiet PATTERN (or -q if you don't have GNU Grep). You can use the same pattern in a pipeline if grep is the last command in the pipeline or you use set -o pipefail to get the first non-zero exit code in the pipeline as the exit code of the whole pipeline.

So in your case it would simply be:

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

Upvotes: 0

Related Questions