Update script version to 4.9 and enhance error handling
This commit is contained in:
@@ -20,7 +20,7 @@ set -euo pipefail
|
|||||||
# =========================
|
# =========================
|
||||||
# Version
|
# Version
|
||||||
# =========================
|
# =========================
|
||||||
SCRIPT_VERSION="4.8"
|
SCRIPT_VERSION="4.9"
|
||||||
|
|
||||||
# =========================
|
# =========================
|
||||||
# Globals / Defaults
|
# Globals / Defaults
|
||||||
@@ -58,6 +58,16 @@ SYSTEM_KEYRING="/usr/share/keyrings/linuxmint-repo.gpg"
|
|||||||
# Error handling
|
# Error handling
|
||||||
ON_ERROR_BACKUP_HINT=""
|
ON_ERROR_BACKUP_HINT=""
|
||||||
|
|
||||||
|
on_err() {
|
||||||
|
local rc=$?
|
||||||
|
local line="${BASH_LINENO[0]:-unknown}"
|
||||||
|
echo "ERROR: FAILED at line ${line} (exit ${rc})."
|
||||||
|
echo "ERROR: Command: ${BASH_COMMAND}"
|
||||||
|
[[ -n "${ON_ERROR_BACKUP_HINT:-}" ]] && echo "${ON_ERROR_BACKUP_HINT}"
|
||||||
|
exit "$rc"
|
||||||
|
}
|
||||||
|
trap on_err ERR
|
||||||
|
|
||||||
# =========================
|
# =========================
|
||||||
# Pretty output
|
# Pretty output
|
||||||
# =========================
|
# =========================
|
||||||
@@ -100,7 +110,7 @@ Usage (command-first):
|
|||||||
sudo bash $0 convert --i-accept-the-risk [options]
|
sudo bash $0 convert --i-accept-the-risk [options]
|
||||||
sudo bash $0 rollback /root/ubuntu-to-mint-backup-YYYYMMDD-HHMMSS
|
sudo bash $0 rollback /root/ubuntu-to-mint-backup-YYYYMMDD-HHMMSS
|
||||||
|
|
||||||
Usage (options-first ALSO supported in v${SCRIPT_VERSION}):
|
Usage (options-first ALSO supported):
|
||||||
sudo bash $0 [options] doctor
|
sudo bash $0 [options] doctor
|
||||||
sudo bash $0 [options] plan
|
sudo bash $0 [options] plan
|
||||||
sudo bash $0 [options] convert --i-accept-the-risk
|
sudo bash $0 [options] convert --i-accept-the-risk
|
||||||
@@ -264,7 +274,7 @@ timeshift_snapshot_best_effort() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
# =========================
|
# =========================
|
||||||
# Mint repo key bootstrap (no keyservers)
|
# Keyrings
|
||||||
# =========================
|
# =========================
|
||||||
gpg_key_file_has_keyid() {
|
gpg_key_file_has_keyid() {
|
||||||
local f="$1"
|
local f="$1"
|
||||||
@@ -272,6 +282,16 @@ gpg_key_file_has_keyid() {
|
|||||||
gpg --batch --with-colons --show-keys "$f" 2>/dev/null | awk -F: '$1=="pub"||$1=="sub"{print toupper($5)}' | grep -qx "$(echo "$keyid" | tr '[:lower:]' '[:upper:]')"
|
gpg --batch --with-colons --show-keys "$f" 2>/dev/null | awk -F: '$1=="pub"||$1=="sub"{print toupper($5)}' | grep -qx "$(echo "$keyid" | tr '[:lower:]' '[:upper:]')"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ubuntu_archive_keyring_path() {
|
||||||
|
# Needed for plan mode temp APT root signature verification.
|
||||||
|
DEBIAN_FRONTEND=noninteractive apt-get install -y ubuntu-keyring >/dev/null 2>&1 || true
|
||||||
|
if [[ -r /usr/share/keyrings/ubuntu-archive-keyring.gpg ]]; then
|
||||||
|
echo "/usr/share/keyrings/ubuntu-archive-keyring.gpg"
|
||||||
|
return 0
|
||||||
|
fi
|
||||||
|
die "Ubuntu archive keyring not found at /usr/share/keyrings/ubuntu-archive-keyring.gpg (install ubuntu-keyring?)"
|
||||||
|
}
|
||||||
|
|
||||||
mint_keyring_build_from_linuxmint_keyring_deb() {
|
mint_keyring_build_from_linuxmint_keyring_deb() {
|
||||||
local out_keyring="$1"
|
local out_keyring="$1"
|
||||||
[[ -n "$out_keyring" ]] || die "mint_keyring_build_from_linuxmint_keyring_deb: missing output path"
|
[[ -n "$out_keyring" ]] || die "mint_keyring_build_from_linuxmint_keyring_deb: missing output path"
|
||||||
@@ -346,7 +366,7 @@ mint_keyring_build_from_linuxmint_keyring_deb() {
|
|||||||
info "Using key candidate: $chosen"
|
info "Using key candidate: $chosen"
|
||||||
if [[ "$chosen" == *.asc || "$chosen" == *.key ]]; then
|
if [[ "$chosen" == *.asc || "$chosen" == *.key ]]; then
|
||||||
grep -q "BEGIN PGP PUBLIC KEY BLOCK" "$chosen" 2>/dev/null || { rm -rf "$tmpdir"; die "Selected key candidate is not armored PGP: $chosen"; }
|
grep -q "BEGIN PGP PUBLIC KEY BLOCK" "$chosen" 2>/dev/null || { rm -rf "$tmpdir"; die "Selected key candidate is not armored PGP: $chosen"; }
|
||||||
gpg --batch --dearmor -o "$tmp_out" "$chosen" || { rm -rf "$tmpdir"; die "gpg dearmor failed for key candidate"; }
|
gpg --batch --dearmor -o "$tmp_out" "$chosen"
|
||||||
else
|
else
|
||||||
cp -a "$chosen" "$tmp_out"
|
cp -a "$chosen" "$tmp_out"
|
||||||
fi
|
fi
|
||||||
@@ -408,7 +428,9 @@ detect_ubuntu_mirrors() {
|
|||||||
|
|
||||||
write_mint_sources_system() {
|
write_mint_sources_system() {
|
||||||
local list="/etc/apt/sources.list.d/official-package-repositories.list"
|
local list="/etc/apt/sources.list.d/official-package-repositories.list"
|
||||||
local keyring="$SYSTEM_KEYRING"
|
local mint_keyring="$SYSTEM_KEYRING"
|
||||||
|
local ubuntu_keyring
|
||||||
|
ubuntu_keyring="$(ubuntu_archive_keyring_path)"
|
||||||
|
|
||||||
detect_ubuntu_mirrors
|
detect_ubuntu_mirrors
|
||||||
|
|
||||||
@@ -418,13 +440,13 @@ write_mint_sources_system() {
|
|||||||
# Generated by ubuntu-to-mint-convert-v3.sh on $(date -Is)
|
# Generated by ubuntu-to-mint-convert-v3.sh on $(date -Is)
|
||||||
#
|
#
|
||||||
# Linux Mint repository:
|
# Linux Mint repository:
|
||||||
deb [signed-by=${keyring}] ${MINT_MIRROR%/} ${TARGET_MINT} main upstream import backport
|
deb [signed-by=${mint_keyring}] ${MINT_MIRROR%/} ${TARGET_MINT} main upstream import backport
|
||||||
|
|
||||||
# Ubuntu base repositories:
|
# Ubuntu base repositories:
|
||||||
deb ${UBUNTU_ARCHIVE_MIRROR%/} ${UBUNTU_BASE} main restricted universe multiverse
|
deb [signed-by=${ubuntu_keyring}] ${UBUNTU_ARCHIVE_MIRROR%/} ${UBUNTU_BASE} main restricted universe multiverse
|
||||||
deb ${UBUNTU_ARCHIVE_MIRROR%/} ${UBUNTU_BASE}-updates main restricted universe multiverse
|
deb [signed-by=${ubuntu_keyring}] ${UBUNTU_ARCHIVE_MIRROR%/} ${UBUNTU_BASE}-updates main restricted universe multiverse
|
||||||
deb ${UBUNTU_ARCHIVE_MIRROR%/} ${UBUNTU_BASE}-backports main restricted universe multiverse
|
deb [signed-by=${ubuntu_keyring}] ${UBUNTU_ARCHIVE_MIRROR%/} ${UBUNTU_BASE}-backports main restricted universe multiverse
|
||||||
deb ${UBUNTU_SECURITY_MIRROR%/} ${UBUNTU_BASE}-security main restricted universe multiverse
|
deb [signed-by=${ubuntu_keyring}] ${UBUNTU_SECURITY_MIRROR%/} ${UBUNTU_BASE}-security main restricted universe multiverse
|
||||||
EOF
|
EOF
|
||||||
|
|
||||||
if [[ -f /etc/apt/sources.list ]]; then
|
if [[ -f /etc/apt/sources.list ]]; then
|
||||||
@@ -490,7 +512,6 @@ session_name_for_edition() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
ensure_lightdm_on_boot() {
|
ensure_lightdm_on_boot() {
|
||||||
# Make LightDM the default display manager and ensure graphical boot.
|
|
||||||
if [[ ! -d /run/systemd/system ]]; then
|
if [[ ! -d /run/systemd/system ]]; then
|
||||||
warn "systemd not detected; cannot enable LightDM on boot in this environment."
|
warn "systemd not detected; cannot enable LightDM on boot in this environment."
|
||||||
return 0
|
return 0
|
||||||
@@ -498,33 +519,23 @@ ensure_lightdm_on_boot() {
|
|||||||
|
|
||||||
info "Ensuring LightDM starts on boot (graphical.target + default display manager)..."
|
info "Ensuring LightDM starts on boot (graphical.target + default display manager)..."
|
||||||
|
|
||||||
# Unmask LightDM in case something previously masked it
|
|
||||||
systemctl unmask lightdm >/dev/null 2>&1 || true
|
systemctl unmask lightdm >/dev/null 2>&1 || true
|
||||||
|
|
||||||
# Ensure the default DM marker is LightDM
|
|
||||||
echo "/usr/sbin/lightdm" > /etc/X11/default-display-manager || true
|
echo "/usr/sbin/lightdm" > /etc/X11/default-display-manager || true
|
||||||
|
|
||||||
# Debian/Ubuntu DM selection often uses update-alternatives
|
|
||||||
if have_cmd update-alternatives; then
|
if have_cmd update-alternatives; then
|
||||||
update-alternatives --set x-display-manager /usr/sbin/lightdm >/dev/null 2>&1 || true
|
update-alternatives --set x-display-manager /usr/sbin/lightdm >/dev/null 2>&1 || true
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# Ensure graphical boot target
|
|
||||||
systemctl set-default graphical.target >/dev/null 2>&1 || true
|
systemctl set-default graphical.target >/dev/null 2>&1 || true
|
||||||
systemctl enable graphical.target >/dev/null 2>&1 || true
|
systemctl enable graphical.target >/dev/null 2>&1 || true
|
||||||
|
|
||||||
# Enable LightDM for boot
|
|
||||||
systemctl enable lightdm >/dev/null 2>&1 || true
|
systemctl enable lightdm >/dev/null 2>&1 || true
|
||||||
|
|
||||||
# Prevent GDM from stealing the greeter
|
|
||||||
if systemctl list-unit-files | awk '{print $1}' | grep -qx 'gdm3.service'; then
|
if systemctl list-unit-files | awk '{print $1}' | grep -qx 'gdm3.service'; then
|
||||||
systemctl disable --now gdm3 >/dev/null 2>&1 || true
|
systemctl disable --now gdm3 >/dev/null 2>&1 || true
|
||||||
systemctl mask gdm3 >/dev/null 2>&1 || true
|
systemctl mask gdm3 >/dev/null 2>&1 || true
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# Restart the active DM if we can
|
|
||||||
systemctl restart lightdm >/dev/null 2>&1 || true
|
systemctl restart lightdm >/dev/null 2>&1 || true
|
||||||
|
|
||||||
ok "LightDM configured to start on boot."
|
ok "LightDM configured to start on boot."
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -533,21 +544,11 @@ ensure_lightdm_defaults() {
|
|||||||
sess="$(session_name_for_edition)"
|
sess="$(session_name_for_edition)"
|
||||||
|
|
||||||
info "Configuring LightDM defaults for edition=${EDITION} (session=${sess})"
|
info "Configuring LightDM defaults for edition=${EDITION} (session=${sess})"
|
||||||
|
|
||||||
DEBIAN_FRONTEND=noninteractive apt-get install -y lightdm slick-greeter
|
DEBIAN_FRONTEND=noninteractive apt-get install -y lightdm slick-greeter
|
||||||
|
|
||||||
# Keep Ubuntu's gdm3 installed (if present) but ensure it can't win.
|
|
||||||
if systemctl is-enabled gdm3 >/dev/null 2>&1; then
|
|
||||||
warn "Disabling gdm3 (keeping installed)."
|
|
||||||
systemctl disable --now gdm3 || true
|
|
||||||
systemctl mask gdm3 || true
|
|
||||||
if [[ -f /etc/gdm3/custom.conf ]]; then
|
|
||||||
sed -i 's/^[#[:space:]]*WaylandEnable=.*/WaylandEnable=false/' /etc/gdm3/custom.conf || true
|
|
||||||
grep -q '^WaylandEnable=' /etc/gdm3/custom.conf || echo 'WaylandEnable=false' >> /etc/gdm3/custom.conf
|
|
||||||
fi
|
|
||||||
fi
|
|
||||||
|
|
||||||
mkdir -p /etc/lightdm/lightdm.conf.d
|
mkdir -p /etc/lightdm/lightdm.conf.d
|
||||||
|
|
||||||
|
# Comment out any existing user-session settings (keep files)
|
||||||
shopt -s nullglob
|
shopt -s nullglob
|
||||||
for f in /etc/lightdm/lightdm.conf.d/*.conf; do
|
for f in /etc/lightdm/lightdm.conf.d/*.conf; do
|
||||||
[[ "$(basename "$f")" == "99-ubuntu2mint.conf" ]] && continue
|
[[ "$(basename "$f")" == "99-ubuntu2mint.conf" ]] && continue
|
||||||
@@ -596,9 +597,7 @@ EOF
|
|||||||
chmod 644 "$dmrc" || true
|
chmod 644 "$dmrc" || true
|
||||||
done
|
done
|
||||||
|
|
||||||
# This is the baked-in boot behavior you asked for:
|
|
||||||
ensure_lightdm_on_boot
|
ensure_lightdm_on_boot
|
||||||
|
|
||||||
ok "LightDM defaults applied; default session set to ${sess}."
|
ok "LightDM defaults applied; default session set to ${sess}."
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -621,8 +620,7 @@ apply_mintupdate_icon_diversion() {
|
|||||||
# Post-install sanity checks
|
# Post-install sanity checks
|
||||||
# =========================
|
# =========================
|
||||||
post_install_sanity() {
|
post_install_sanity() {
|
||||||
local out_file="$1"
|
local out_file="${1:-/tmp/post-convert-validation.txt}"
|
||||||
[[ -n "$out_file" ]] || out_file="/tmp/post-convert-validation.txt"
|
|
||||||
|
|
||||||
{
|
{
|
||||||
echo "Post-conversion validation ($(date -Is))"
|
echo "Post-conversion validation ($(date -Is))"
|
||||||
@@ -650,7 +648,7 @@ post_install_sanity() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
# =========================
|
# =========================
|
||||||
# Plan mode (temp APT root)
|
# Plan mode helpers
|
||||||
# =========================
|
# =========================
|
||||||
apt_tmp_run() {
|
apt_tmp_run() {
|
||||||
local tmpapt="$1"; shift
|
local tmpapt="$1"; shift
|
||||||
@@ -665,6 +663,24 @@ apt_tmp_run() {
|
|||||||
apt-get "${extra[@]}" "$@"
|
apt-get "${extra[@]}" "$@"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
plan_fix_tmpapt_perms() {
|
||||||
|
local tmpapt="$1"
|
||||||
|
|
||||||
|
# Allow _apt sandbox to traverse and write partial lists
|
||||||
|
chmod 755 "$tmpapt" || true
|
||||||
|
chmod 755 "$tmpapt"/{etc,usr,var} 2>/dev/null || true
|
||||||
|
chmod 755 "$tmpapt"/var/{lib,cache} 2>/dev/null || true
|
||||||
|
chmod 755 "$tmpapt"/var/lib/apt 2>/dev/null || true
|
||||||
|
chmod 755 "$tmpapt"/var/cache/apt 2>/dev/null || true
|
||||||
|
|
||||||
|
if id _apt >/dev/null 2>&1; then
|
||||||
|
chown -R _apt:root "$tmpapt/var/lib/apt/lists/partial" 2>/dev/null || true
|
||||||
|
chown -R _apt:root "$tmpapt/var/cache/apt/archives/partial" 2>/dev/null || true
|
||||||
|
chmod 755 "$tmpapt/var/lib/apt/lists/partial" 2>/dev/null || true
|
||||||
|
chmod 755 "$tmpapt/var/cache/apt/archives/partial" 2>/dev/null || true
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
plan_mode() {
|
plan_mode() {
|
||||||
need_root
|
need_root
|
||||||
ensure_no_apt_locks
|
ensure_no_apt_locks
|
||||||
@@ -674,19 +690,29 @@ plan_mode() {
|
|||||||
|
|
||||||
local tmpapt
|
local tmpapt
|
||||||
tmpapt="$(mktemp -d)"
|
tmpapt="$(mktemp -d)"
|
||||||
mkdir -p "${tmpapt}/etc/apt/sources.list.d" "${tmpapt}/etc/apt/preferences.d" "${tmpapt}/var/lib/apt/lists/partial" "${tmpapt}/var/cache/apt/archives/partial" "${tmpapt}/usr/share/keyrings"
|
mkdir -p "${tmpapt}/etc/apt/sources.list.d" \
|
||||||
|
"${tmpapt}/etc/apt/preferences.d" \
|
||||||
|
"${tmpapt}/var/lib/apt/lists/partial" \
|
||||||
|
"${tmpapt}/var/cache/apt/archives/partial" \
|
||||||
|
"${tmpapt}/usr/share/keyrings"
|
||||||
|
|
||||||
|
plan_fix_tmpapt_perms "$tmpapt"
|
||||||
|
|
||||||
local tmp_keyring="${tmpapt}/usr/share/keyrings/linuxmint-repo.gpg"
|
local tmp_keyring="${tmpapt}/usr/share/keyrings/linuxmint-repo.gpg"
|
||||||
mint_keyring_build_from_linuxmint_keyring_deb "$tmp_keyring"
|
mint_keyring_build_from_linuxmint_keyring_deb "$tmp_keyring"
|
||||||
|
|
||||||
|
local ubuntu_keyring
|
||||||
|
ubuntu_keyring="$(ubuntu_archive_keyring_path)"
|
||||||
|
|
||||||
detect_ubuntu_mirrors
|
detect_ubuntu_mirrors
|
||||||
|
|
||||||
cat > "${tmpapt}/etc/apt/sources.list" <<EOF
|
cat > "${tmpapt}/etc/apt/sources.list" <<EOF
|
||||||
deb [signed-by=${tmp_keyring}] ${MINT_MIRROR%/} ${TARGET_MINT} main upstream import backport
|
deb [signed-by=${tmp_keyring}] ${MINT_MIRROR%/} ${TARGET_MINT} main upstream import backport
|
||||||
deb ${UBUNTU_ARCHIVE_MIRROR%/} ${UBUNTU_BASE} main restricted universe multiverse
|
|
||||||
deb ${UBUNTU_ARCHIVE_MIRROR%/} ${UBUNTU_BASE}-updates main restricted universe multiverse
|
deb [signed-by=${ubuntu_keyring}] ${UBUNTU_ARCHIVE_MIRROR%/} ${UBUNTU_BASE} main restricted universe multiverse
|
||||||
deb ${UBUNTU_ARCHIVE_MIRROR%/} ${UBUNTU_BASE}-backports main restricted universe multiverse
|
deb [signed-by=${ubuntu_keyring}] ${UBUNTU_ARCHIVE_MIRROR%/} ${UBUNTU_BASE}-updates main restricted universe multiverse
|
||||||
deb ${UBUNTU_SECURITY_MIRROR%/} ${UBUNTU_BASE}-security main restricted universe multiverse
|
deb [signed-by=${ubuntu_keyring}] ${UBUNTU_ARCHIVE_MIRROR%/} ${UBUNTU_BASE}-backports main restricted universe multiverse
|
||||||
|
deb [signed-by=${ubuntu_keyring}] ${UBUNTU_SECURITY_MIRROR%/} ${UBUNTU_BASE}-security main restricted universe multiverse
|
||||||
EOF
|
EOF
|
||||||
|
|
||||||
cat > "${tmpapt}/etc/apt/preferences.d/50-linuxmint-conversion.pref" <<'EOF'
|
cat > "${tmpapt}/etc/apt/preferences.d/50-linuxmint-conversion.pref" <<'EOF'
|
||||||
@@ -723,14 +749,14 @@ EOF
|
|||||||
local rc=${PIPESTATUS[0]}
|
local rc=${PIPESTATUS[0]}
|
||||||
set -e
|
set -e
|
||||||
|
|
||||||
|
rm -rf "$tmpapt"
|
||||||
|
|
||||||
if [[ $rc -ne 0 ]]; then
|
if [[ $rc -ne 0 ]]; then
|
||||||
warn "Plan simulation failed (exit $rc). Review: $plan_out"
|
warn "Plan simulation failed (exit $rc). Review: $plan_out"
|
||||||
rm -rf "$tmpapt"
|
|
||||||
exit $rc
|
exit $rc
|
||||||
fi
|
fi
|
||||||
|
|
||||||
ok "Plan completed successfully. Review: $plan_out"
|
ok "Plan completed successfully. Review: $plan_out"
|
||||||
rm -rf "$tmpapt"
|
|
||||||
}
|
}
|
||||||
|
|
||||||
# =========================
|
# =========================
|
||||||
@@ -829,10 +855,6 @@ convert() {
|
|||||||
info "Reinstalling x11-common (fixes Xsession has_option issues)..."
|
info "Reinstalling x11-common (fixes Xsession has_option issues)..."
|
||||||
DEBIAN_FRONTEND=noninteractive apt-get $(apt_opts_common) install --reinstall x11-common || true
|
DEBIAN_FRONTEND=noninteractive apt-get $(apt_opts_common) install --reinstall x11-common || true
|
||||||
|
|
||||||
info "Ensuring GNOME RandR runtime libs present (best-effort)..."
|
|
||||||
DEBIAN_FRONTEND=noninteractive apt-get $(apt_opts_common) install \
|
|
||||||
libgnome-rr-4-2t64 libgnome-desktop-4-2t64 libgnome-bg-4-2t64 || true
|
|
||||||
|
|
||||||
ensure_lightdm_defaults
|
ensure_lightdm_defaults
|
||||||
|
|
||||||
mkdir -p "$backup_dir"
|
mkdir -p "$backup_dir"
|
||||||
|
|||||||
Reference in New Issue
Block a user