Created
May 19, 2026 16:32
-
-
Save OndraZizka/ce75bdf064848121c0b18d270b0fe391 to your computer and use it in GitHub Desktop.
Fix LUKS mounting after HDD power loss - "file already exists"
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| #!/bin/bash | |
| ## Cleans up stale LUKS device mappings. | |
| ## Usage: sudo ./fix_ghost_luks.sh | |
| set -e | |
| # Color output | |
| RED='\033[0;31m' | |
| GREEN='\033[0;32m' | |
| YELLOW='\033[1;33m' | |
| BLUE='\033[0;34m' | |
| NC='\033[0m' # No Color | |
| # Device details | |
| LUKS_UUID="71136d07-e496-4b36-8eb8-e2b9771d80d0" | |
| LUKS_NAME="luks-${LUKS_UUID}" | |
| DM_MAJOR="252" | |
| DM_MINOR="2" | |
| MOUNT_POINT="/media/o/ToshD" | |
| # Check if running with sudo | |
| if [[ $EUID -ne 0 ]]; then | |
| echo -e "${RED}This script must be run with sudo${NC}" | |
| echo "Usage: sudo $0" | |
| exit 1 | |
| fi | |
| echo -e "${BLUE}========================================${NC}" | |
| echo -e "${BLUE} Ghost LUKS Device Cleanup Script${NC}" | |
| echo -e "${BLUE}========================================${NC}" | |
| echo "" | |
| echo "Target device: $LUKS_NAME" | |
| echo "UUID: $LUKS_UUID" | |
| echo "Mount point: $MOUNT_POINT" | |
| echo "" | |
| # Step 1: Check if device mapping exists | |
| echo -e "${YELLOW}[1/5]${NC} Checking for stale device mapping..." | |
| if dmsetup ls 2>/dev/null | grep -q "$LUKS_NAME"; then | |
| echo -e " ${GREEN}✓${NC} Found device mapping (${DM_MAJOR}:${DM_MINOR})" | |
| # Try to unmount first | |
| if mountpoint -q "$MOUNT_POINT" 2>/dev/null; then | |
| echo -e " ${YELLOW}→${NC} Mount point still active, unmounting..." | |
| if umount -f "$MOUNT_POINT" 2>/dev/null; then | |
| echo -e " ${GREEN}✓${NC} Unmounted successfully" | |
| else | |
| echo -e " ${RED}✗${NC} Failed to unmount, trying lazy unmount..." | |
| umount -l "$MOUNT_POINT" 2>/dev/null || true | |
| fi | |
| fi | |
| # Remove device mapping | |
| echo -e " ${YELLOW}→${NC} Removing device mapping..." | |
| if dmsetup remove "$LUKS_NAME" 2>/dev/null; then | |
| echo -e " ${GREEN}✓${NC} Device mapping removed via dmsetup" | |
| elif cryptsetup close "$LUKS_NAME" 2>/dev/null; then | |
| echo -e " ${GREEN}✓${NC} Device closed via cryptsetup" | |
| else | |
| echo -e " ${RED}✗${NC} Failed to remove mapping, trying forced removal..." | |
| dmsetup remove -f "$LUKS_NAME" 2>/dev/null || true | |
| fi | |
| else | |
| echo -e " ${GREEN}✓${NC} No device mapping found (already clean)" | |
| fi | |
| echo "" | |
| # Step 2: Clean udev database | |
| echo -e "${YELLOW}[2/5]${NC} Clearing udev database entry..." | |
| UDEV_PATH="/run/udev/data/b${DM_MAJOR}:${DM_MINOR}" | |
| if [[ -f "$UDEV_PATH" ]]; then | |
| echo -e " ${GREEN}✓${NC} Found udev entry at $UDEV_PATH" | |
| echo "About to 'rm -f $UDEV_PATH" | |
| read | |
| rm -f "$UDEV_PATH" | |
| echo -e " ${GREEN}✓${NC} Removed udev database entry" | |
| else | |
| echo -e " ${GREEN}✓${NC} No udev entry found (already clean)" | |
| fi | |
| echo "" | |
| # Step 3: Reload udev | |
| echo -e "${YELLOW}[3/5]${NC} Reloading udev rules and triggering..." | |
| udevadm control --reload-rules >/dev/null 2>&1 | |
| udevadm trigger >/dev/null 2>&1 | |
| echo -e " ${GREEN}✓${NC} udev reloaded and triggered" | |
| echo "" | |
| # Step 4: Reload systemd | |
| echo -e "${YELLOW}[4/5]${NC} Reloading systemd daemon..." | |
| systemctl daemon-reload >/dev/null 2>&1 | |
| echo -e " ${GREEN}✓${NC} systemd daemon reloaded" | |
| echo "" | |
| # Step 5: Restart udisks2 | |
| echo -e "${YELLOW}[5/5]${NC} Restarting udisks2 service..." | |
| if systemctl is-active --quiet udisks2; then | |
| systemctl restart udisks2 >/dev/null 2>&1 | |
| echo -e " ${GREEN}✓${NC} udisks2 restarted" | |
| else | |
| echo -e " ${YELLOW}→${NC} udisks2 not running, skipping restart" | |
| fi | |
| echo "" | |
| # Verification | |
| echo -e "${BLUE}========================================${NC}" | |
| echo -e "${BLUE} Verification${NC}" | |
| echo -e "${BLUE}========================================${NC}" | |
| echo "" | |
| # Check 1: Device mapping gone | |
| echo -ne "Device mapping status: " | |
| if ! dmsetup ls 2>/dev/null | grep -q "$LUKS_UUID" 2>/dev/null; then | |
| echo -e "${GREEN}✓ REMOVED${NC}" | |
| else | |
| echo -e "${RED}✗ STILL EXISTS${NC}" | |
| fi | |
| # Check 2: udev entry gone | |
| echo -ne "udev database entry: " | |
| if [[ ! -f "$UDEV_PATH" ]]; then | |
| echo -e "${GREEN}✓ CLEANED${NC}" | |
| else | |
| echo -e "${RED}✗ STILL EXISTS${NC}" | |
| fi | |
| # Check 3: Symlinks gone | |
| echo -ne "Device mapper symlinks: " | |
| if ! ls /dev/mapper/luks-${LUKS_UUID}* 2>/dev/null | grep -q .; then | |
| echo -e "${GREEN}✓ REMOVED${NC}" | |
| else | |
| echo -e "${YELLOW}~ still present (will auto-clean on next mount)${NC}" | |
| fi | |
| # Check 4: Mount point state | |
| echo -ne "Mount point status: " | |
| if ! mountpoint -q "$MOUNT_POINT" 2>/dev/null; then | |
| echo -e "${GREEN}✓ UNMOUNTED${NC}" | |
| else | |
| echo -e "${RED}✗ STILL MOUNTED${NC}" | |
| fi | |
| echo "" | |
| echo -e "${GREEN}========================================${NC}" | |
| echo -e "${GREEN} Cleanup Complete!${NC}" | |
| echo -e "${GREEN}========================================${NC}" | |
| echo "" | |
| echo -e "Next steps:" | |
| echo " 1. Reconnect the ToshD USB drive" | |
| echo " 2. Open file manager (Nautilus)" | |
| echo " 3. It should prompt to unlock the device" | |
| echo " 4. Enter the LUKS passphrase" | |
| echo "" | |
| echo "If you still get errors:" | |
| echo " - Check kernel logs: sudo dmesg | tail -20" | |
| echo " - Check udisks2 logs: journalctl -u udisks2 -n 50" | |
| echo " - Use Disks application for graphical interface" | |
| echo "" |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment