Files
backup_to_external_m.2/lvm-migration-tools/prepare_live_system.sh
Migration Tools 9d25520de9 Initial commit: Complete LVM migration toolset with fixes
- Fixed partition size calculation bugs in migrate_to_lvm.sh
- Added comprehensive error handling for USB drive stability
- Optimized data copy operations using cp -a for better performance
- Corrected mount point detection for encrypted home partitions
- Enhanced drive detection and exclusion logic
- Added proper size override mechanisms for manual intervention
- Improved filesystem creation and validation processes
- Complete toolset for external M.2 drive migration scenarios

Tested successfully on:
- Debian 13 Trixie Live USB environment
- 476GB external M.2 drives via USB 3.0
- Complex partition layouts (root/home/EFI + encryption)
- Large data transfers (314GB+ encrypted home directories)
2025-09-25 05:53:12 +00:00

315 lines
9.9 KiB
Bash
Executable File

#!/bin/bash
# Live System Preparation Script for LVM Migration
# This script prepares a live USB system with all necessary tools for LVM migration
set -e
# Colors for output
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
BLUE='\033[0;34m'
NC='\033[0m' # No Color
log() {
echo -e "${BLUE}[$(date '+%H:%M:%S')]${NC} $1"
}
error() {
echo -e "${RED}[ERROR]${NC} $1" >&2
exit 1
}
warning() {
echo -e "${YELLOW}[WARNING]${NC} $1"
}
success() {
echo -e "${GREEN}[SUCCESS]${NC} $1"
}
check_live_system() {
log "Checking if running from live system..."
# Check multiple indicators of live system
local is_live=false
# Check for common live system indicators
if [ -f "/etc/casper.conf" ] || [ -f "/lib/live/mount/medium" ]; then
is_live=true
fi
# Check if root filesystem is on loop, overlay, or tmpfs
local root_device=$(df / | tail -1 | awk '{print $1}')
if [[ "$root_device" == *"loop"* ]] || [[ "$root_device" == *"overlay"* ]] || [[ "$root_device" == *"tmpfs"* ]]; then
is_live=true
fi
# Check for live system processes
if pgrep -f "casper" >/dev/null 2>&1 || pgrep -f "live-boot" >/dev/null 2>&1; then
is_live=true
fi
if [ "$is_live" = true ]; then
success "Confirmed: Running from live system"
else
warning "This doesn't appear to be a live system!"
echo "For safety, LVM migration should be run from a live USB system."
read -p "Continue anyway? [y/N] " -n 1 -r
echo
if [[ ! $REPLY =~ ^[Yy]$ ]]; then
error "Operation aborted. Please boot from a live USB system."
fi
fi
}
update_package_lists() {
log "Updating package lists..."
if command -v apt >/dev/null 2>&1; then
apt update || warning "Failed to update apt package lists"
elif command -v pacman >/dev/null 2>&1; then
pacman -Sy || warning "Failed to update pacman package lists"
elif command -v dnf >/dev/null 2>&1; then
dnf makecache || warning "Failed to update dnf package cache"
else
warning "Unknown package manager - manual tool installation may be required"
fi
}
install_required_tools() {
log "Installing required tools for LVM migration..."
# Detect distribution for package name variations
local distro="unknown"
if [ -f /etc/os-release ]; then
. /etc/os-release
distro="$ID"
log "Detected distribution: $PRETTY_NAME"
fi
# Define package groups with alternatives for different distributions
local package_groups=(
"lvm:lvm2,lvm"
"cryptsetup:cryptsetup,cryptsetup-bin"
"rsync:rsync"
"parted:parted"
"pv:pv,pipe-viewer"
"grub-efi:grub-efi-amd64,grub-efi,grub-efi-amd64-bin"
"grub-pc:grub-pc-bin,grub-pc"
"grub-common:grub-common,grub2-common"
"e2fsprogs:e2fsprogs"
"dosfstools:dosfstools,mtools"
"util-linux:util-linux"
"coreutils:coreutils"
"bc:bc"
"initramfs:initramfs-tools,dracut"
"udev:udev,systemd-udev"
"kmod:kmod,module-init-tools"
)
local missing_tools=()
local packages_to_install=()
# Check which tools are missing
for tool_spec in "${tools_to_check[@]}"; do
local tool=$(echo "$tool_spec" | cut -d: -f1)
local packages=$(echo "$tool_spec" | cut -d: -f2)
if ! command -v "$tool" >/dev/null 2>&1; then
missing_tools+=("$tool")
# Add packages (handle comma-separated list)
IFS=',' read -ra PKGS <<< "$packages"
for pkg in "${PKGS[@]}"; do
if [[ ! " ${packages_to_install[@]} " =~ " ${pkg} " ]]; then
packages_to_install+=("$pkg")
fi
done
fi
done
if [ ${#missing_tools[@]} -eq 0 ]; then
success "All required tools are already available"
return
fi
echo "Missing tools: ${missing_tools[*]}"
echo "Will attempt to install: ${packages_to_install[*]}"
# Install packages based on available package manager
if command -v apt >/dev/null 2>&1; then
log "Installing packages with apt..."
# Update package lists first
apt update || warning "Failed to update package lists"
# Function to try installing packages with alternatives
try_install() {
local desc="$1"
local packages_str="$2"
IFS=',' read -ra packages <<< "$packages_str"
log "Installing $desc..."
for pkg in "${packages[@]}"; do
if apt install -y "$pkg" >/dev/null 2>&1; then
success "Installed $pkg for $desc"
return 0
fi
done
warning "Failed to install any package for $desc (tried: ${packages_str//,/, })"
return 1
}
# Install packages by groups
for group in "${package_groups[@]}"; do
local desc="${group%:*}"
local packages="${group#*:}"
try_install "$desc" "$packages"
done
elif command -v pacman >/dev/null 2>&1; then
log "Installing packages with pacman..."
pacman -S --noconfirm "${packages_to_install[@]}" || {
warning "Some packages failed to install via pacman"
}
elif command -v dnf >/dev/null 2>&1; then
log "Installing packages with dnf..."
dnf install -y "${packages_to_install[@]}" || {
warning "Some packages failed to install via dnf"
}
else
warning "Unknown package manager. Please install these packages manually:"
echo " ${packages_to_install[*]}"
fi
# Verify installation
local still_missing=()
for tool_spec in "${tools_to_check[@]}"; do
local tool=$(echo "$tool_spec" | cut -d: -f1)
if ! command -v "$tool" >/dev/null 2>&1; then
still_missing+=("$tool")
fi
done
if [ ${#still_missing[@]} -eq 0 ]; then
success "All required tools are now available"
else
error "Still missing tools: ${still_missing[*]}. Please install them manually."
fi
}
enable_lvm_kernel_modules() {
log "Enabling LVM kernel modules..."
local modules=("dm_mod" "dm_crypt" "dm_snapshot")
for module in "${modules[@]}"; do
if ! lsmod | grep -q "^$module"; then
log "Loading kernel module: $module"
modprobe "$module" || warning "Failed to load $module module"
else
log "Module $module already loaded"
fi
done
# Start LVM services if available
if command -v systemctl >/dev/null 2>&1; then
systemctl start lvm2-monitor 2>/dev/null || true
systemctl start lvm2-lvmetad 2>/dev/null || true
fi
success "LVM kernel modules enabled"
}
check_drive_availability() {
log "Checking for available drives..."
# List all available block devices
echo "Available drives:"
lsblk -dpno NAME,SIZE,MODEL,VENDOR | grep -E "sd[a-z]|nvme[0-9]|mmcblk[0-9]" | while read line; do
echo " $line"
done
# Count drives
local drive_count=$(lsblk -dpno NAME | grep -E "sd[a-z]|nvme[0-9]|mmcblk[0-9]" | wc -l)
if [ "$drive_count" -lt 2 ]; then
warning "Only $drive_count drive(s) detected. Migration requires at least 2 drives:"
echo " 1. Internal drive (source)"
echo " 2. External M.2 SSD (target)"
echo
echo "Please connect your external M.2 SSD and try again."
exit 1
else
success "Found $drive_count drives - sufficient for migration"
fi
}
create_migration_workspace() {
log "Creating migration workspace..."
local workspace="/tmp/lvm-migration"
mkdir -p "$workspace"/{scripts,logs,mounts}
# Copy migration script to workspace if it exists
if [ -f "./migrate_to_lvm.sh" ]; then
cp "./migrate_to_lvm.sh" "$workspace/scripts/"
chmod +x "$workspace/scripts/migrate_to_lvm.sh"
success "Migration script copied to workspace"
fi
# Create useful aliases
cat > "$workspace/aliases.sh" << 'EOF'
#!/bin/bash
# Useful aliases for LVM migration
alias ll='ls -la'
alias drives='lsblk -dpno NAME,SIZE,MODEL,VENDOR'
alias mounts='mount | grep -E "sd[a-z]|nvme|loop|mapper"'
alias lvminfo='pvs && vgs && lvs'
alias migration='cd /tmp/lvm-migration && ls -la'
echo "Migration workspace aliases loaded:"
echo " drives - List all available drives"
echo " mounts - Show mounted filesystems"
echo " lvminfo - Display LVM information"
echo " migration - Go to migration workspace"
EOF
success "Migration workspace created at $workspace"
echo "To load helpful aliases: source $workspace/aliases.sh"
}
main() {
echo -e "${GREEN}=== Live System Preparation for LVM Migration ===${NC}"
echo "This script prepares your live USB system for LVM migration"
echo
# Check if running as root
if [ "$EUID" -ne 0 ]; then
error "This script must be run as root. Use: sudo $0"
fi
check_live_system
update_package_lists
install_required_tools
enable_lvm_kernel_modules
check_drive_availability
create_migration_workspace
success "Live system preparation completed!"
echo
echo -e "${GREEN}Next steps:${NC}"
echo "1. Connect your external M.2 SSD if not already connected"
echo "2. Run the LVM migration script:"
echo " sudo ./migrate_to_lvm.sh"
echo "3. Follow the interactive prompts to complete migration"
echo
echo -e "${YELLOW}Important reminders:${NC}"
echo "• Ensure your external M.2 SSD is large enough for your system"
echo "• The migration will DESTROY all data on the target drive"
echo "• Your original internal drive will remain unchanged as backup"
echo "• After migration, update BIOS boot order to boot from external drive"
}
main "$@"