0

I am writing a shell script that will ask me if I'd like to check my system for updates when I log in. If I say yes, it checks and lists the packages to be upgraded. Then, it asks me if I would like to upgrade those packages. I would like the command that asks me if I'd like to upgrade the packages to only run when there is one or more package that needs to be upgraded that was listed after sudo apt update && apt list --upgradeable. How can I do this? Here is my script so far:

read -r -p "Would you like to check your system for updates? [Y/n] " input
case $input in
[yY][eE][sS]|[yY])
sudo apt update && apt list --upgradeable 
read -r -p "Would you like to update your system? [Y/n] " input
case $input in
[yY][eE][sS]|[yY])
sudo apt upgrade && sudo apt autoremove && sudo apt autoclean
;;
[nN][oO]|[nN])
clear
;;
*)
clear && echo "Invalid input..."
;;
esac
;;
[nN][oO]|[nN])
clear
;;
*)
clear && echo "Invalid input..."
;;
esac

It basically needs to be like this: if this bit of text is in the previous command's output, then run the next command.

Any help is much appreciated. Thanks!

2 Answers2

2

Get the number of available updates with:

/usr/lib/update-notifier/apt-check
# returns (for example) 12;4

/usr/lib/update-notifier/apt-check --human-readable
# returns (for example)
  12 packages can be updated.
  4 updates are security updates.

/usr/lib/update-notifier/apt-check |& cut -d";" -f1
# returns (for example) 12

To test if there are available updates, use the last command and test his ouput against 0.

Here is a simple script that will do your stuff
Note that it does not handle bad inputs, only catches '', 'yes', 'YeS', 'y', 'Y' to continue proceeding. If no 'yes' input, then simply exit script.

#!/bin/bash

read -r -p "Would you like to check your system for updates? [Y/n] " response
  response=${response,,} # tolower
  if ! ([[ $response =~ ^(yes|y| ) ]] || [[ -z $response ]]); then
    exit
  fi
sudo apt update > /dev/null 2>&1
nUpgradables=$(/usr/lib/update-notifier/apt-check |& cut -d";" -f1)

if [ $nUpgradables -gt 0 ]; then
  echo ${nUpgradables}" packages can be updated"
  read -r -p "Would you like to update your system? [Y/n] " input
  response=${response,,} # tolower
  if ! ([[ $response =~ ^(yes|y| ) ]] || [[ -z $response ]]); then
    exit
  fi
  sudo apt-get -f install # that is good to do too
  sudo apt upgrade        # upgrade, not 'upgrades'
  sudo apt autoremove
  sudo apt autoclean
else
  echo "No upgrade available"
fi
cmak.fr
  • 8,696
  • I'm receiving this error: -bash: [: too many arguments – GNULinuxOnboard Sep 07 '19 at 06:52
  • It seems to work besides this issue, but I'll have to wait for new updates to be sure. – GNULinuxOnboard Sep 07 '19 at 06:56
  • @TheMATEMan: updated ;) - if you still have an error, plz run bash -x /path/to/script.sh and tell me what line# to watch – cmak.fr Sep 07 '19 at 06:57
  • The issue persists. Lines 9 and 7 seem to be the issues: `+ read -r -p 'Would you like to check your system for updates? [Y/n] ' response Would you like to check your system for updates? [Y/n] y
    • response=y
    • [[ y =~ ^(yes|y| ) ]]
    • sudo apt-get update

    ++ /usr/lib/update-notifier/apt-check ++ cut '-d;' -f1

    • nUpgradables='h.sh: line 7: /usr/lib/update-notifier/apt-check: No such file or directory'
    • '[' h.sh: line 7: /usr/lib/update-notifier/apt-check: No such file or directory -gt 0 ']'

    h.sh: line 9: [: too many arguments

    • echo 'No upgrade available'

    No upgrade available `

    – GNULinuxOnboard Sep 07 '19 at 07:09
  • @TheMATEMan: try to re-create the script file from updated code. (i tested it twice, its ok) – cmak.fr Sep 07 '19 at 07:31
  • you can compact response abit [[ ${response,,} =~ ^(y|yes)$ ]] || exit 0 –  Sep 23 '19 at 16:54
1
#!/bin/bash

# update package list.
aptitude --quiet=2 update

# count upgradeable packages.
read -r c < <(aptitude --quiet=2 search '?narrow(?upgradable, ?not(?action(hold)))' | wc -l)

while true; do
    (( $c <= 0 )) && break
    read -r -p "You have $c upgradable packages, would you like to upgrade? [Y/n] " i
    case ${i,,} in
        [y]|[yes])
            aptitude upgrade # --assume-yes --quiet=2
            break
            ;;
        [n]|[no])
            echo "No action taken..."
            break
            ;;
        *)
            echo "Invalid input..."
            continue
            ;;
    esac
done

exit 0

Version 2

#!/bin/bash

# update package list.
apt-get --quiet=2 update

# count upgradeable packages.
read -r c < <(apt-get --no-act --quiet=2 upgrade | grep -c '^Inst')

while true; do
    (( $c <= 0 )) && break
    read -r -p "You have $c upgradable packages, would you like to upgrade? [Y/n] " i
    case ${i,,} in
        [y]|[yes])
            apt-get upgrade # --assume-yes --quiet=2
            break
            ;;
        [n]|[no])
            echo "No action taken..."
            break
            ;;
        *)
            echo "Invalid input..."
            continue
            ;;
    esac
done

exit 0
  • Well, I added this to my server’s .bashrc, like a fool and didn’t test it first. It has an error executing and it closes the ssh connection. I now have no way to fix the server. – GNULinuxOnboard Sep 23 '19 at 13:32
  • Luckily, I have a recent backup. I’ll test this in a minute in a script other than .bashrc. – GNULinuxOnboard Sep 23 '19 at 13:34
  • It does not detect aptitude as a command. Should I try to install it or should I use apt-get or apt instead of aptitude? Or is this script specific to aptitude? – GNULinuxOnboard Sep 23 '19 at 15:28
  • I installed aptitude and ran it as root and It worked flawlessly. I will mark this answer as correct. – GNULinuxOnboard Sep 23 '19 at 15:58