diff --git a/migrate2rocky.sh b/migrate2rocky.sh index 7abbbae..0d37ac9 100644 --- a/migrate2rocky.sh +++ b/migrate2rocky.sh @@ -43,7 +43,9 @@ exec > >(tee -a "$logfile") 2> >(tee -a "$logfile" >&2) #errcolor=$(tput setaf 1) #blue=$(tput setaf 4) #nocolor=$(tput op) -unset errcolor blue nocolor +errcolor= +blue= +nocolor= export LANG=en_US.UTF-8 shopt -s nullglob @@ -95,7 +97,7 @@ os-release () ( # be adequate for our needs here. pkg_ver() ( ver=$(rpm -q --qf '%{VERSION}\n' "$1") || return 2 - if [[ $(sort -V <<<"$ver"$'\n'"$2" | head -1) != $2 ]]; then + if [[ $(sort -V <<<"$ver"$'\n'"$2" | head -1) != "$2" ]]; then return 1 fi return 0 @@ -112,7 +114,7 @@ bin_check() { fi # Check the platform. - if [[ $(os-release PLATFORM_ID) != $SUPPORTED_PLATFORM ]]; then + if [[ $(os-release PLATFORM_ID) != "$SUPPORTED_PLATFORM" ]]; then exit_message "This script must be run on an EL8 distribution. Migration from other distributions is not supported." fi @@ -142,7 +144,7 @@ bin_check() { fi if (( ${#missing[@]} )); then - exit_message "Commands not found: ${missing[@]}. Possible bad PATH setting or corrupt installation." + exit_message "Commands not found: ${missing[*]}. Possible bad PATH setting or corrupt installation." fi } @@ -150,7 +152,8 @@ bin_check() { # info for the resulting package. Note that we explicitly disable the epel repo # as a special-case below to avoid having the extras repository map to epel. repoquery () { - local name val prev result=$( + local name val prev result + result=$( dnf -q --setopt=epel.excludepkgs=epel-release repoquery -i "$1" || exit_message "Failed to fetch info for package $1." ) @@ -225,11 +228,36 @@ provides_pkg () ( provides=$(dnf -q provides "$1" | awk '{print $1; nextfile}') || return 1 set +o pipefail - pkg=$(dnf -q repoquery --queryformat '%{NAME}' "$provides") || + pkg=$(rpm -q --queryformat '%{NAME}\n' "$provides") || + pkg=$(dnf -q repoquery --queryformat '%{NAME}\n' "$provides") || exit_message "Can't get package name for $provides." printf '%s\n' "$pkg" ) +# If you pass an empty arg as one of the package specs to rpm it will match +# every package on the system. This funtion simply strips out any empty args +# and passes the rest to rpm to avoid this side-effect. +saferpm () ( + args=() + for a in "$@"; do + if [[ $a ]]; then + args+=("$a") + fi + done + rpm "${args[@]}" +) + +# And a similar function for dnf +safednf () ( + args=() + for a in "$@"; do + if [[ $a ]]; then + args+=("$a") + fi + done + dnf "${args[@]}" +) + collect_system_info () { # Check the efi mount first, so we can bail before wasting time on all these # other checks if it's not there. @@ -282,8 +310,8 @@ collect_system_info () { done printf '%s\n' '' '' "Found the following repositories which map from $PRETTY_NAME to Rocky Linux 8:" - column -t -N "$PRETTY_NAME,Rocky Linux 8" < <(for r in "${!repo_map[@]}"; do - printf '%s %s\n' "${repo_map[$r]}" "$r" + column -t -s $'\t' -N "$PRETTY_NAME,Rocky Linux 8" < <(for r in "${!repo_map[@]}"; do + printf '%s\t%s\n' "${repo_map[$r]}" "$r" done) printf '\n%s' "${blue}Getting system package names for $PRETTY_NAME$nocolor." @@ -330,37 +358,38 @@ collect_system_info () { for pkg in "${!provides_pkg_map[@]}"; do printf '.' prov=${provides_pkg_map[$pkg]} - pkg_map[$pkg]=$(provides_pkg $prov) || + pkg_map[$pkg]=$(provides_pkg "$prov") || exit_message "Can't get package that provides $prov." done for prov in "${addl_provide_removes[@]}"; do printf '.' local pkg; - pkg=$(provides_pkg $prov) || continue + pkg=$(provides_pkg "$prov") || continue addl_pkg_removes+=("$pkg") done printf '%s\n' '' '' "Found the following system packages which map from $PRETTY_NAME to Rocky Linux 8:" - column -t -N "$PRETTY_NAME,Rocky Linux 8" < <(for p in "${!pkg_map[@]}"; do - printf '%s %s\n' "${pkg_map[$p]}" "$p" + column -t -s $'\t' -N "$PRETTY_NAME,Rocky Linux 8" < <(for p in "${!pkg_map[@]}"; do + printf '%s\t%s\n' "${pkg_map[$p]}" "$p" done) printf '%s\n' '' "${blue}Getting list of installed system packages$nocolor." - readarray -t installed_packages < <(rpm -qa --queryformat="%{NAME}\n" "${pkg_map[@]}") + + readarray -t installed_packages < <(saferpm -qa --queryformat="%{NAME}\n" "${pkg_map[@]}") declare -g -A installed_pkg_check installed_pkg_map for p in "${installed_packages[@]}"; do installed_pkg_check[$p]=1 done for p in "${!pkg_map[@]}"; do - if [[ ${installed_pkg_check[${pkg_map[$p]}]} ]]; then + if [[ ${pkg_map[$p]} && ${installed_pkg_check[${pkg_map[$p]}]} ]]; then installed_pkg_map[$p]=${pkg_map[$p]} fi done; printf '%s\n' '' "We will replace the following $PRETTY_NAME packages with their Rocky Linux 8 equivalents" - column -t -N "Packages to be Removed,Packages to be Installed" < <( + column -t -s $'\t' -N "Packages to be Removed,Packages to be Installed" < <( for p in "${!installed_pkg_map[@]}"; do - printf '%s %s\n' "${installed_pkg_map[$p]}" "$p" + printf '%s\t%s\n' "${installed_pkg_map[$p]}" "$p" done ) @@ -380,7 +409,7 @@ collect_system_info () { # Get a list of system enabled modules. readarray -t enabled_modules < <( set -e -o pipefail - dnf -q "${repo_map[@]/#/--repo=}" module list --enabled | + safednf -q "${repo_map[@]/#/--repo=}" module list --enabled | awk ' $1 == "@modulefailsafe", /^$/ {next} $1 == "Name", /^$/ {if ($1!="Name" && !/^$/) print $1":"$2} @@ -445,7 +474,7 @@ package_swaps() { done # Use dnf shell to swap the system packages out. - dnf -y shell --disablerepo=\* --noautoremove \ + safednf -y shell --disablerepo=\* --noautoremove \ --setopt=protected_packages= --setopt=keepcache=True \ "${dnfparameters[@]}" \ <