#!/usr/bin/env bash # # JbTecWiz Support Centre -- generated fix script # # Fault : Boot drops to emergency mode after an fstab change # Fix : Repair the entry from emergency mode # Source: https://jbtecwiz.com/support/lnx-fstab-emergency # # Run as : Emergency shell # Expect : 20 minutes # Risk : medium # Reversible : yes # # WHEN THIS IS THE RIGHT FIX # A local device entry is wrong. # # HOW TO UNDO IT # Comment out the new line entirely and reboot -- the system will come # up without that mount. # # 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 " Boot drops to emergency mode after an fstab change" echo " Repair the entry from emergency mode" echo echo " Risk: medium Reversible 20 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 if step 1 'Log in at the maintenance prompt with the root password, then find which mount failed.' '' cmd 'systemctl --failed' 'journalctl -xb | grep -i '\''failed to mount'\'' '; then systemctl --failed journalctl -xb | grep -i 'failed to mount' 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 'Remount the root filesystem read-write so you can edit.' '' cmd 'mount -o remount,rw /'; then mount -o remount,rw / 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 'Check the real UUIDs against what fstab claims.' 'A UUID copied by hand with one character wrong is the single most common cause, and it is invisible unless you compare them side by side.' cmd 'blkid' 'cat /etc/fstab'; then blkid cat /etc/fstab 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 'Correct the entry, or add nofail so a missing device can never stop the boot again.' 'nofail is worth adding to every non-essential mount as a matter of course. It turns '\''the server will not boot'\'' into '\''a directory is empty'\''.' cmd 'vi /etc/fstab'; then vi /etc/fstab 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 'Test the file before rebooting -- this is the step that stops a second trip to the console.' '' cmd 'systemctl daemon-reload' 'mount -a && echo '\''fstab is good'\'''; then systemctl daemon-reload mount -a && echo 'fstab is good' 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 'Reboot.' '' cmd 'systemctl reboot'; then systemctl reboot 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 'The machine boots normally and everything is mounted.' if [ "$DRYRUN" = "0" ]; then findmnt --verify systemctl is-system-running 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-fstab-emergency" else echo " Finished." fi echo prose 'To undo: Comment out the new line entirely and reboot -- the system will come up without that mount.' rule