skip to Main Content

i am trying to create a condition statement that checks if the grep found if a package is installed.
if it is true , then the package should not be installed , and if it is false , then the package should be installed.
i am always getting the same result package is not installed no matter which value i put
please help (in my case the all packages are installed and grep finds a match.
here is code:

chk1=$(yum list installed | grep rpmdevtools) 
chk2=$(yum list installed | grep rpmbuild)
chk3=$(yum list installed | grep rpmdev)
if [[ $chk1 -ne 0 && "$chk2" -ne 0 && "$chk3" -ne 0 ]];then
   echo "package exists"
   sleep 5
else
   echo "package doesn't exists installing .."
   sleep 5
   sudo yum install wget -y
   wget http://mirror.centos.org/centos/7/os/x86_64/Packages/rpmdevtools-8.3-5.el7.noarch.rpm
   sudo yum install rpmdevtools-8.3-5.el7.noarch.rpm -y
fi

3

Answers


  1. You’re mixing 2 types of results here : result (i.e. displayed text) and return value.

    TL;DR

    You can verify if the variable $chkX is not empty with [[ ! -z ${chkX} ]], such as :

    if [[ ! -z ${chk1} ]] && [[ ! -z ${chk2} ]] && [[ ! -z ${chk3} ]]; then
    [...]
    

    Or you can do something like this, based on exit codes.

    yum list installed | grep -q vim
    if [[ $? -eq 0 ]]; then
      # do your stuff here when package is installed
    else
      #.. do your stuff here when package isn't installed ..
    fi
    

    or

    if yum list installed | grep -q 'vim' ;then
      # do your stuff here when package is installed
    else
      # .. do your stuff here when package isn't installed ..
    fi
    
    

    When executing in a subshell through $(yum …) you are storing the result (i.e. displayed text) that’s echoed by the command.
    For instance:

    $> yum list installed | grep vim
    vim-common.x86_64                                 2:8.2.3755-1.fc35                    @updates       
    

    If you want the return code or exit code, it’s accessible through $?.
    For example:

    $> ls
    [...]
    $> echo $?
    0
    $> ls toto
    ls: cannot access 'toto': No such file or directory
    $> echo $?
    2
    

    Note every command changes the exit code.
    So accessing twice $? will change its value.

    $> ls toto
    ls: cannot access 'toto': No such file or directory
    $> echo $?
    2
    $> echo $?
    0
    

    In your case, you’re testing if the text given by yum is mathematically equal to 0:

    chk3=$(yum list installed | grep rpmdev)
    if [[ $chk1 -ne 0 && "$chk2" -ne 0 && "$chk3" -ne 0 ]];then
                                                 ^^^^^^
    

    It’s not possible because :

    • no package found -> empty variable
    • one or many package found -> single or multiline text with package information.
    • and you’ll never get 0.

    If you run it with test you have various cases of failure:

    # note: rpmdevtools is not installed on by computer
    $> chk1=$(yum list installed | grep rpmdevtools) 
    $> test $chk1 -ne 0
    bash: test: -ne: unary operator expected
    
    # multiple vim-* packages are installed
    $> chk1=$(yum list installed | grep vim) 
    $> test $chk1 -ne 0
    bash: test: too many arguments
    
    Login or Signup to reply.
  2. I’m not familiar with yum, there may be a better way to check, but this will make your if statement work:

    if
        yum list installed | grep -q rpmdevtools &&
        yum list installed | grep -q rpmbuild &&
        yum list installed | grep -q rpmdev
    then
    

    I also recommend adding -w to grep, to match a whole word.

    If yum list installed is a slow command, consider saving the output in a variable, and grepping that (instead of running it three times):

    list=$(yum list installed)
    
    if
        echo "$list" | grep -q rpmdevtools &&
        echo "$list" | grep -q rpmbuild &&
        echo "$list" | grep -q rpmdev
    then
    
    Login or Signup to reply.
  3. The immediate problem is that -ne checks for numeric equality; of course the output from grep is not going to be the number 0, so all of your checks fail.

    You seem to be overcomplicating things significantly anyway. yum list installed optionally accepts a list of packages to check.

    if yum list installed rpmdevtools rpmbuild rpmdev >/dev/null 2>&1
    then
       echo "$0: package exists" >&1
    else
       echo "$0: package doesn't exist; installing ..." >&2
       sudo yum install -y wget
       wget http://mirror.centos.org/centos/7/os/x86_64/Packages/rpmdevtools-8.3-5.el7.noarch.rpm
       sudo yum install -y rpmdevtools-8.3-5.el7.noarch.rpm
    fi
    

    Notice the convention for diagnostic messages to include the script name $0 and print to standard error >&2, and how we avoid the absolutely user-hostile abomination of sleeping in the middle. If you want to give users a chance to decide whether they really want to proceed with the planned action, display a separate prompt (and ideally make it possible to override from the command line, just like yum install -y lets you say you don’t want a prompt).

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search