#!/usr/bin/env bash # # JbTecWiz Support Centre -- generated fix script # # Fault : A cloned machine will not boot -- device names and UUIDs have changed # Fix : Give the clone new identifiers # Source: https://jbtecwiz.com/support/lnx-sto-uuid-fstab # # Run as : Rescue media, filesystems unmounted # Expect : 40 minutes # Risk : high # Reversible : yes # # WHEN THIS IS THE RIGHT FIX # A cloned disk shares UUIDs with the original and both are attached. # # HOW TO UNDO IT # UUIDs can be set back explicitly with tune2fs -U if the # originals were recorded. # # Walks the fix one step at a time and asks before each. Steps with no # command are yours to do -- it prints those and waits. DRYRUN=1 prints # without executing; UNATTENDED=1 does not ask. # # -------------------------------------------------------------------- # NO WARRANTY - USE AT YOUR OWN RISK # # This script is provided by JbTecWiz as-is and with no warranty of any # kind, express or implied. You run it entirely at your own risk. # # JbTecWiz accepts no liability for any loss or damage arising from its # use, including but not limited to data loss, downtime, or configuration # changes that turn out to be wrong for your system. # # You are responsible for reading this script before running it, for # satisfying yourself that it suits the machine in front of you, and for # having a working backup first. Some steps cannot be undone. # -------------------------------------------------------------------- set -uo pipefail DRYRUN="${DRYRUN:-0}" UNATTENDED="${UNATTENDED:-0}" failed=0 rule() { printf "\n%s\n" "$(printf '-%.0s' $(seq 1 70))"; if [ $# -gt 0 ]; then echo "$1"; fi; } prose() { echo "$1" | fold -s -w 74 | sed "s/^/ /"; } # Returns 0 when the caller should run the command, 1 when it should not. # A manual step always returns 1 -- there is nothing for the caller to run. step() { # step [command lines...] local n="$1" dotext="$2" why="$3" mode="$4"; shift 4 rule " Step $n of 6" prose "$dotext" if [ -n "$why" ]; then echo; prose "$why"; fi if [ "$mode" = "manual" ]; then echo; echo " -> Do this yourself, then press Enter to carry on." if [ "$UNATTENDED" = "0" ] && [ "$DRYRUN" = "0" ]; then read -r _; fi return 1 fi echo; printf " %s\n" "$@"; echo if [ "$DRYRUN" = "1" ]; then echo " (dry run -- not executed)"; return 1; fi if [ "$UNATTENDED" = "0" ]; then read -r -p " Run this step? [Y]es / [S]kip / [Q]uit " a case "$a" in [Qq]*) echo " Stopped at your request."; exit 0 ;; [Ss]*) echo " Skipped."; return 1 ;; esac fi return 0 } rule echo " A cloned machine will not boot -- device names and UUIDs have changed" echo " Give the clone new identifiers" echo echo " Risk: high Reversible 40 minutes" echo prose 'No warranty. Use at your own risk - JbTecWiz accepts no liability. Read it before you run it, and have a backup.' rule echo if [ "$UNATTENDED" = "0" ] && [ "$DRYRUN" = "0" ]; then read -r -p " Ready? [y/N] " go case "$go" in [Yy]*) ;; *) echo " Nothing was changed."; exit 0;; esac fi step 1 'Boot from rescue media with only the clone attached where possible.' '' manual || true if step 2 'Find the duplicates.' '' cmd 'sudo blkid | sort -t= -k2'; then sudo blkid | sort -t= -k2 if [ $? -ne 0 ]; then failed=$((failed+1)) echo " Step 2 failed. The rest of the fix may depend on it." >&2 fi fi if step 3 'Change the filesystem UUID. The command differs by filesystem type.' '' cmd 'sudo tune2fs -U random /dev/sdb1 # ext4' 'sudo xfs_admin -U generate /dev/sdb1 # xfs' 'sudo swaplabel -U $(uuidgen) /dev/sdb2 # swap'; then sudo tune2fs -U random /dev/sdb1 # ext4 sudo xfs_admin -U generate /dev/sdb1 # xfs sudo swaplabel -U $(uuidgen) /dev/sdb2 # swap if [ $? -ne 0 ]; then failed=$((failed+1)) echo " Step 3 failed. The rest of the fix may depend on it." >&2 fi fi if step 4 'Rename the LVM volume group if LVM is in use -- two groups with the same name is worse than duplicate UUIDs.' 'With two identically named volume groups visible, LVM activates one of them and there is no way to predict which. This makes a clone boot from the original'\''s disk without any error to indicate it.' cmd 'sudo vgdisplay | grep -E '\''VG Name|VG UUID'\''' 'sudo vgrename OldVGUUID newvg0'; then sudo vgdisplay | grep -E 'VG Name|VG UUID' sudo vgrename OldVGUUID newvg0 if [ $? -ne 0 ]; then failed=$((failed+1)) echo " Step 4 failed. The rest of the fix may depend on it." >&2 fi fi if step 5 'Update fstab and the boot configuration with the new UUIDs.' '' cmd 'sudo blkid' 'sudo nano /etc/fstab' 'sudo update-grub || sudo grub2-mkconfig -o /boot/grub2/grub.cfg'; then sudo blkid sudo nano /etc/fstab sudo update-grub || sudo grub2-mkconfig -o /boot/grub2/grub.cfg if [ $? -ne 0 ]; then failed=$((failed+1)) echo " Step 5 failed. The rest of the fix may depend on it." >&2 fi fi if step 6 'Rebuild the initramfs so the root UUID it embeds is correct.' '' cmd 'sudo update-initramfs -u -k all || sudo dracut -f --regenerate-all'; then sudo update-initramfs -u -k all || sudo dracut -f --regenerate-all if [ $? -ne 0 ]; then failed=$((failed+1)) echo " Step 6 failed. The rest of the fix may depend on it." >&2 fi fi rule " Confirm it worked" prose 'Both machines boot with the original and the clone attached, each using its own filesystems.' if [ "$DRYRUN" = "0" ]; then blkid; findmnt / fi rule if [ "$failed" -gt 0 ]; then echo " Finished with $failed failed step(s)." echo " Read the full write-up at https://jbtecwiz.com/support/lnx-sto-uuid-fstab" else echo " Finished." fi echo prose 'To undo: UUIDs can be set back explicitly with tune2fs -U if the originals were recorded.' rule