0

I have written a bash script which is checking OS version and count for available security patches according to OS distribution.

The query here is the script is not working for Ubuntu OS. The script is as below:

#!/bin/bash


# Detecting OS Distribution
if [ -f /etc/os-release ]; then
  . /etc/os-release
  OS=$PRETTY_NAME

elif [ -f /etc/redhat-release ]; then

   REDHAT=$(cat /etc/redhat-release)

else
   echo " OS is not supported "
fi

#Check how many packages for security and available to update
if [[ $OS == *"Red Hat"* ]] || [[ $OS == *"Amazon Linux"* ]] || [[ $OS == 
    *"CentOS"*  ]] || [[ $REDHAT == *"Red Hat"*  ]] ; then

    SECPKGCNT=$(sudo yum list-security --security | awk 'NR>2 {print last} 
{last=$0}' | wc -l)
    echo "${OS},${REDHAT},${SECPKGCNT}"

elif [[ $OS == *"Ubuntu"* ]] ;then

    SECPKGCOUNT=$(sudo apt list --upgradable 2>/dev/null | grep "\-security" 
    | wc -l)
    echo "${OS},${SECPKGCOUNT}"
   else
  echo " No security packages to update"
   fi

O/p in ubuntu machine:

root@ip-XXXX:~# sh -x getos.sh
+ [ -f /etc/os-release ]
+ . /etc/os-release
+ NAME=Ubuntu
+ VERSION=14.04.5 LTS, Trusty Tahr
+ ID=ubuntu
+ ID_LIKE=debian
+ PRETTY_NAME=Ubuntu 14.04.5 LTS
+ VERSION_ID=14.04
+ HOME_URL=http://www.ubuntu.com/
+ SUPPORT_URL=http://help.ubuntu.com/
+ BUG_REPORT_URL=http://bugs.launchpad.net/ubuntu/
+ OS=Ubuntu 14.04.5 LTS
+ [[ Ubuntu 14.04.5 LTS = *Red Hat* ]]
getos.sh: 29: getos.sh: [[: not found
+ [[ Ubuntu 14.04.5 LTS = *Amazon Linux* ]]
getos.sh: 29: getos.sh: [[: not found
+ [[ Ubuntu 14.04.5 LTS = *CentOS* ]]
getos.sh: 29: getos.sh: [[: not found
+ [[ = *Red Hat* ]]
getos.sh: 29: getos.sh: [[: not found
+ [ Ubuntu 14.04.5 LTS = *Ubuntu* ]
getos.sh: 34: [: Ubuntu: unexpected operator
+ echo  No security packages to update
No security packages to update

In above ubuntu system the script is not working as expected, I mean it should print OS version and count of security patches.

  • 1
    Is that really your script? That would give a syntax error if you ran it. You can't randomly break commands with newlines. What actually happens if you run this? It works fine on an Ubuntu I tested it on when I fix the syntax errors. – terdon Nov 25 '19 at 13:35
  • Yes its written today only. @terdon Can you please let me know what is the syntax error here. – Santosh Garole Nov 25 '19 at 13:41

1 Answers1

2

You have two main issues. First, you are running the script with sh, not bash but are using bash features (the [[ construct) that are not supported by sh. So you need to run bash getos.sh or just ./getos.sh if it is executable.

Next, you cannot break commands wherever you like, you need to break on a control operator. So this will fail:

SECPKGCOUNT=$(sudo apt list --upgradable 2>/dev/null | grep "\-security" 
| wc -l)

While this would work:

SECPKGCOUNT=$(sudo apt list --upgradable 2>/dev/null | grep "\-security" | 
wc -l)

Then, a few minor issues. Your first if ... elif .. else means that if /etc/os-release exists, you will never do the rest. So you can never have a situation where both OS and REDHAT are set. However, you seem to be expecting both, and I see no reason why /etc/os-release would be missing from a Red Hat system. So I think you probably want separate if instead of if ... elif.

Finally, some of your commands (the awk and the grep | wc) can be simplified, you're creating variables that aren't actually needed and the whole thing can be made a bit simpler with:

#!/bin/bash

if [ -f /etc/os-release ]; then
  . /etc/os-release
fi
if [ -f /etc/redhat-release ]; then
  REDHAT=$(cat /etc/redhat-release)
fi

if [[ $PRETTY_NAME == *"Red Hat"* ]] || [[ $PRETTY_NAME == *"Amazon Linux"* ]] ||
   [[ $PRETTY_NAME ==  *"CentPRETTY_NAME"* ]] || [[ $REDHAT == *"Red Hat"*  ]]; then
  SECPKGCNT=$(sudo yum list-security --security | awk 'NR>2 {k++}END{print k}')
  PRETTY_NAME="$PRETTY_NAME,$REDHAT";
elif [[ "$PRETTY_NAME" == *"Ubuntu"* ]] ;then
  SECPKGCNT=$(sudo apt list --upgradable 2>/dev/null | grep -c "\-security")
else
  echo " OS is not supported "
  exit
fi

echo "$PRETTY_NAME,$SECPKGCNT"
terdon
  • 242,166
  • Contrast the advice to test the capability and not the string in https://unix.stackexchange.com/a/41735/5132 , where the behaviour is conditional upon which package tool is (first) found, not on a display name which varies. (The fact that it is variable on RHEL was the underlying motivation for the behaviour that is described in RHEL bug #1240624.) Even testing ID would be better. – JdeBP Mar 10 '20 at 14:40