#!/usr/bin/env bash # # JbTecWiz Support Centre -- generated fix script # # Fault : LVM volume group not found at boot # Fix : Deal with a missing physical volume # Source: https://jbtecwiz.com/support/lnx-lvm-missing # # Run as : Emergency shell or live USB # Expect : 1 hour # Risk : high # Reversible : NO -- read the undo note below # # WHEN THIS IS THE RIGHT FIX # A PV is genuinely absent. Understand what is on it before doing # anything -- this is the point at which data is lost or saved. # # HOW TO UNDO IT # None. LVM metadata backups in /etc/lvm/archive can restore a previous # configuration with vgcfgrestore, but cannot bring back the missing # disk's contents. # # 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 " LVM volume group not found at boot" echo " Deal with a missing physical volume" echo echo " Risk: high NOT REVERSIBLE 1 hour" 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 if step 1 'Establish what is missing and what it held.' 'If the missing PV held part of a linear LV, that LV has a hole in it. If the LV was mirrored or on RAID, it may be complete. This determines everything that follows.' cmd 'sudo pvs -o +pv_missing' 'sudo vgs -o +vg_missing_pv_count' 'sudo lvs -o lv_name,vg_name,lv_attr,devices'; then sudo pvs -o +pv_missing sudo vgs -o +vg_missing_pv_count sudo lvs -o lv_name,vg_name,lv_attr,devices if [ $? -ne 0 ]; then failed=$((failed+1)) echo " Step 1 failed. The rest of the fix may depend on it." >&2 fi fi if step 2 'Check whether the disk is simply not detected rather than dead.' '' cmd 'lsblk' 'sudo dmesg -T | grep -iE '\''sd |nvme|ata'\'' | tail -20'; then lsblk sudo dmesg -T | grep -iE 'sd |nvme|ata' | tail -20 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 'If it is a cabling or enclosure problem, fix that and rescan -- this is the good outcome.' '' cmd 'echo '\''- - -'\'' | sudo tee /sys/class/scsi_host/host0/scan' 'sudo pvscan --cache'; then echo '- - -' | sudo tee /sys/class/scsi_host/host0/scan sudo pvscan --cache 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 'If the PV is truly gone and you have a backup, restore. If you do not, image what remains before going further.' '' cmd 'sudo ddrescue -f -n /dev/sdb /mnt/backup/sdb.img /mnt/backup/sdb.map'; then sudo ddrescue -f -n /dev/sdb /mnt/backup/sdb.img /mnt/backup/sdb.map 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 'To bring up what survives, activate the group partially. This is a recovery measure, not a repair.' 'Filesystems on an LV with a missing extent will have holes. Mount read-only and copy off what you can; do not write to it.' cmd 'sudo vgchange -ay --activationmode partial vg0'; then sudo vgchange -ay --activationmode partial vg0 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 'Once data is recovered, remove the missing PV and rebuild the group.' 'This permanently drops the LVs that depended on the missing device. Only run it after you have recovered everything you intend to.' cmd 'sudo vgreduce --removemissing --force vg0'; then sudo vgreduce --removemissing --force vg0 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 'vgs reports no missing PVs and the surviving volumes mount.' 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-lvm-missing" else echo " Finished." fi echo prose 'To undo: None. LVM metadata backups in /etc/lvm/archive can restore a previous configuration with vgcfgrestore, but cannot bring back the missing disk'\''s contents.' rule