Reinstalling user package(s) after firmware upgrade

If you want to save and reinstall user installed package(s) after firmware upgrade, this is the script that I use :wink:

Script name: overlaypkgs.sh

#!/bin/sh
#set -x
#by Faruk Tezcan

do_backup() {
  echo
  echo "Checking. Please wait"
  [ -f $filename ] && rm $filename >/dev/null 2>&1
  echo > $filename >/dev/null 2>&1; ret="$?"
  [ $ret -ne 0 ] && { echo "Invalid file name: $filename"; exit 1; }
  rm $filename >/dev/null 2>&1
  [ $(ls -1 /overlay$UP/usr/lib/opkg/info/*.control | wc -l) = 0 ] && {
    echo "No user packages found"; exit 1; }
  echo
  echo "Saved package(s):"
  for EACH in /overlay$UP/usr/lib/opkg/info/*.control
  do
    NAME="$(egrep "^Package: " $EACH | cut -f 2 -d ' ')"
    opkg whatdepends $NAME >/tmp/opkg.whatdepends
    found=0;
    while read line
    do
      if [ $found -eq 0 ]; then {
        [ "$line" == "What depends on root set" ] && found=1 
      } else found=$((found+1))
      fi
    done </tmp/opkg.whatdepends
    [ $found -eq 1 ] && { echo "--> $NAME"; echo $NAME >>$filename; }
  done
  rm /tmp/opkg.whatdepends >/dev/null 2>&1
  echo         
  echo "$filename created"                                        
  echo     
  echo "If you keep your settings during the firmware upgrade process,"
  echo "you will have this file after the upgrade."
  echo
  echo "Otherwise, you should save this file now and finish your"
  echo "firmware upgrade and restore $filename."
  echo
  echo "Enter '$(basename "$0") restore' command to reinstall user-installed packages."                                                                              
} # do_backup

do_restore() {
  [ -f $filename ] || { echo "$filename could not found"; exit 1; }
  opkg update
  echo "Reinstalling user packages"
  echo "Installed packages:" >$filename.log

  for EACH in $(cat $filename); do
    MSG=""
    [ -f /usr/lib/opkg/info/$EACH.control ] && MSG="already installed" || { 
      [ $(opkg info $EACH | wc -l) = 0 ] && MSG="could not found" || opkg install $EACH >>$filename.log; }
    echo "--> $EACH $MSG"
  done

  echo "All the package(s) in $filename processed"
  echo
  echo "Please check '$filename.log'"
} # do_restore

usage() {
cat <<EOF

Usage: $(basename "$0") [OPTION(S)]...[backup|restore]
where: -f <xxx> file name to save package names
                default='/etc/config/overlaypkgs.lst'
       -d       debug option
       -h       show this help text

Backup user installed packages before firmware upgrade and restore after that


EOF

exit 1
} # usage

[ $# -eq 0 ] && usage

filename="/etc/config/overlaypkgs.lst"

while getopts ':df:h' flag
do
  case "${flag}" in
    d    ) set -x ;;
    f    ) filename=$OPTARG ;;
    \?   ) echo "Invalid option: -$OPTARG"; usage ;;
    :    ) echo "Invalid option: -$OPTARG requires an argument"; usage ;;
    h\?* ) usage ;;
  esac
done

shift "$((OPTIND-1))"   # Discard the options and sentinel --
[ $# -ne 1 ] && usage

UP=""; [ -d /overlay/upper ] && UP="/upper"
cmd=$1

case $cmd in
  backup  ) do_backup ;;
  restore ) do_restore ;;
  *       ) echo "Invalid option: -$cmd"; usage; exit 1 ;;
esac

exit 0

Usage :
overlaypkgs.sh backup
This command simply creates a list from /overlay drive for user installed package(s) in /etc/config. If you keep your settings during the firmware upgrade process you will have this file after the upgrade or you can save /etc/config/overlaypkgs.lst file somewhere else.

overlaypkgs.sh restore
Make sure that your created user package(s) list file is ready. Enter this command after the firmware upgrade and enjoy your new system without missing anyhting.

1 Like

With luck, capturing the user-installed packages will be part of v19 -- it is already part of master with slightly different logic

5 Likes

A newer version:

#!/bin/sh
#set -x

do_backup() {
  echo -e "\nChecking. Please wait\n"
  
  opkg update

  rm -f $FILENAME > /dev/null 2>&1
  touch $FILENAME > /dev/null 2>&1
  [ $? -ne 0 ] && { 
    echo "Invalid file name: '$FILENAME'"
    rm -f $FILENAME >/dev/null 2>&1
    exit 1
  }  
  
  COUNT=0  
  CONTROL=$(ls -1 /overlay$UP/usr/lib/opkg/info/*.control 2>&1)
  for EACH in $CONTROL; do
    NAME="$(egrep "^Package: " $EACH | cut -f 2 -d ' ')"
    if [ ! -f /rom/usr/lib/opkg/info/$NAME.control ]; then
      opkg whatdepends $NAME 1>/tmp/opkg.whatdepends 2>/tmp/opkg.error
      [ $? -ne 0 ] && { echo "Error! Check '/tmp/opkg.error'"; exit 1; }
      if [ "$(egrep "depends on $NAME" /tmp/opkg.whatdepends)" == "" ]; then
        [ $COUNT -eq 0 ] && echo -e "\nSaved package(s):" 
        COUNT=$((COUNT+1)); printf "\r%3d-" $COUNT
        echo "$NAME"
        echo $NAME >> $FILENAME
      fi
    fi
  done


  rm -f /tmp/opkg.wahtdepends > /dev/null 2>&1
  
  if [ $COUNT -eq 0 ]; then
    echo -e "\nNo user packages installed"
    exit 1
  fi

  echo -e "\n'$FILENAME' created"
  echo -e "\nIf you keep your settings during the firmware upgrade process,"
  echo -e "you will have $FILENAME after the upgrade."
  echo -e "\nOtherwise, you should save this file now, then finish your"
  echo -e "firmware upgrade and restore $FILENAME."
  echo -e "\nEnter '$(basename "$0") restore' command to reinstall user-installed packages."
} # do_backup

do_restore() {
  [ -f $FILENAME ] || { echo -e  "\n'$FILENAME' not found"; exit 1; }

  CONTROL=$(cat $FILENAME)
  if [ "$CONTROL" == "" ]; then 
    echo "No user installed package(s) found"
    exit 1
  fi  

  opkg update
  echo "Reinstalling user packages" > $FILENAME.log
  echo -e "\nReinstalling user packages\n"
  
  for EACH in $CONTROL; do
    MSG="OK"
    [ -f /usr/lib/opkg/info/$EACH.control ] \
      && MSG="bypassing - already installed" \
      || { [ "$(opkg info $EACH)" == "" ] && MSG="not found" || opkg install $EACH >> $FILENAME.log; }
    echo "$EACH --> $MSG"
    echo "$EACH --> $MSG" >> $FILENAME.log
  done

  echo -e "\nAll the package(s) in $FILENAME processed\n\nPlease check '$FILENAME.log'\n"
} # do_restore

usage() {
cat <<EOF

Usage: $(basename "$0") [OPTION(S)]...[backup|restore]
where: -f <xxx> file name to save package names
                default='/etc/config/overlaypkgs.lst'
       -d       debug option
       -h       show this help text

Backup user installed packages before firmware upgrade and restore after that


EOF

exit 1
} # usage

[ $# -eq 0 ] && usage

FILENAME="/etc/config/overlaypkgs.lst"

while getopts ':df:h' flag
do
  case "${flag}" in
    d    ) set -x ;;
    f    ) FILENAME=$OPTARG ;;
    \?   ) echo "Invalid option: -$OPTARG"; usage ;;
    :    ) echo "Invalid option: -$OPTARG requires an argument"; usage ;;
    h\?* ) usage ;;
  esac
done

shift "$((OPTIND-1))"   # Discard the options and sentinel --
[ $# -ne 1 ] && usage

UP=""; [ -d /overlay/upper ] && UP="/upper"
cmd=$1

case $cmd in
  backup  ) do_backup ;;
  restore ) do_restore ;;
  *       ) echo "Invalid option: -$cmd"; usage ;;
esac

exit 0


1 Like

https://drive.google.com/file/d/12GZKhkevArsceSedqefP0wl_kKWWaVLM/view?usp=sharing

Has this feature been implemented by now? I remember when I upgraded my FB4040 to OpenWRT 21.x it was not implemented, I had to install all my additional packages manually again. I'd like to upgrade to version 23 now, so I'd like to know if I need to run this script by hand or if things will go more smoothly this time.

If feasible you can try luci-app-attendedsysupgrade

1 Like

Sounds interesting. What exactly does this app do?