1

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.

6
  • Are you trying to check what grep returns or what it outputs to stdout? Those are two different things.cmd=$(grep ...) captures the output. Commented Jun 1, 2019 at 19:19
  • I am trying to grep a string ... if the string exists then do something and if it doesn't exist in the grep output do something else. Commented Jun 1, 2019 at 20:48
  • I know you're trying to grep a string. I was trying to understand what result you were trying to examine from grep. According to the manual page for grep, Normally the exit status is 0 if a line is selected, 1 if no lines were selected, and 2 if an error occurred. If you're checking the exit status, then you're going about it the wrong way. If you want the exit status, then check $? right after executing the grep. It will have a value of 0 if there was a match. You don't get the exit status using cmd=$(grep ...). Commented Jun 1, 2019 at 21:16
  • I am not checking the exit code. What I am trying is the following cmd=$(grep -Eiw 'vmx|svm' /proc/cpuinfo) <--- storing the output in cmd variable It could be "someoutput" or "empty" if [[ $cmd -ne 0 ]];then <--- checking that condition with this line and doing something with IF and something else with ELSE but I don't expect $cmd to print something to STDOUT why is $cmd in if [[ $cmd -ne 0 ]];then printing to STDOUT is my gripe Hope this is explained in a better way? Commented Jun 1, 2019 at 21:39
  • If you're not trying to check exit code, then why are you checking the result of grep against a 0? The result of grep -Eiw 'vmx|svm'... is either going to be one or more lines that contain vmx or svm, or no lines at all. In the case of no lines at all, grep does not output a 0. Commented Jun 1, 2019 at 22:17

4 Answers 4

1

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.

Sign up to request clarification or add additional context in comments.

Comments

1

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'.

Comments

1

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.

Comments

0

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
    …

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.