diff --git a/scripts/partbackup b/scripts/partbackup deleted file mode 100644 index e69de29..0000000 diff --git a/scripts/partbackup2 b/scripts/partbackup2 deleted file mode 100644 index e69de29..0000000 diff --git a/scripts/partbackup3 b/scripts/partbackup3 deleted file mode 100644 index 4bc5ea7..0000000 --- a/scripts/partbackup3 +++ /dev/null @@ -1,339 +0,0 @@ -#!/bin/bash - -# Global variables for restore directory -restoreDir="/etc/restore" -backupDir="${restoreDir}/data" - -# Function to create backup directory -create_backup_dir() { - echo "Creating backup directory at ${backupDir}..." - mkdir -p "$backupDir" - echo "Backup directory created." -} - -# Function to backup a partition table -backup_partition() { - local device="$1" - - echo "Backing up partition table for $device..." - sfdisk --dump "$device" > "${backupDir}/partition_table_$(basename "$device").backup" - echo "Partition table backed up to ${backupDir}/partition_table_$(basename "$device").backup" -} - -# Function to backup filesystem UUID -backup_uuid() { - local partition="$1" - - echo "Backing up UUID for $partition..." - blkid "$partition" | awk '{print $2}' > "${backupDir}/uuid_$(basename "$partition").backup" - echo "UUID backed up to ${backupDir}/uuid_$(basename "$partition").backup" -} - -# Function to backup Btrfs subvolumes, excluding snapshots and nested subvolumes -backup_btrfs_subvolumes() { - local mount_point="$1" - local subvol_path - local subvol_name - - echo "Backing up Btrfs subvolumes from $mount_point to ${backupDir}..." - mkdir -p "${backupDir}/btrfs_subvolumes" - btrfs subvolume list -p "$mount_point" | while read -r line; do - subvol_path=$(echo "$line" | awk '{print $NF}') - subvol_name=$(basename "$subvol_path") - - # Skip snapshots and subvolumes under .snapshots - if [[ "$subvol_path" == *.snapshots/* || "$subvol_path" == ".snapshots" ]]; then - continue - fi - - echo "Backing up subvolume $subvol_name" - btrfs subvolume snapshot "$mount_point/$subvol_path" "${backupDir}/btrfs_subvolumes/$subvol_name" - done - echo "Btrfs subvolumes backed up to ${backupDir}/btrfs_subvolumes" -} - -# Function to backup current mount points and options -backup_mount_points() { - echo "Backing up current mount points and options..." - mount | grep "^/dev" > "${backupDir}/mount_points.backup" - echo "Mount points backed up to ${backupDir}/mount_points.backup" -} - -# Function to restore Btrfs subvolumes to /mnt/restore, excluding snapshots and nested subvolumes -restore_btrfs_subvolumes() { - local mount_point="$1" - local subvol_snapshot - local subvol_name - - echo "Restoring Btrfs subvolumes from ${backupDir}/btrfs_subvolumes to /mnt/restore/$mount_point..." - mkdir -p "/mnt/restore$mount_point" - for subvol_snapshot in "${backupDir}/btrfs_subvolumes"/*; do - if [[ -d "$subvol_snapshot" ]]; then - subvol_name=$(basename "$subvol_snapshot") - - # Restore subvolume to the mount point - echo "Restoring subvolume $subvol_name" - btrfs subvolume snapshot "$subvol_snapshot" "/mnt/restore$mount_point/$subvol_name" - fi - done - echo "Btrfs subvolumes restored to /mnt/restore$mount_point" -} - -# Function to restore mount points to /mnt/restore, supporting Btrfs subvolumes -restore_mount_points() { - local original_device - local device - local mount_point - local mount_opts - local subvol - local fs_type - - if [[ -f "${backupDir}/mount_points.backup" ]]; then - echo "Restoring mount points from ${backupDir}/mount_points.backup to /mnt/restore..." - mkdir -p /mnt/restore - while IFS= read -r line; do - original_device=$(echo "$line" | awk '{print $1}') - mount_point=$(echo "$line" | awk '{print $3}') - mount_opts=$(echo "$line" | awk -F' ' '{for(i=4;i<=NF;i++){print $i}}' | tr -d '()') - - # Extract and remove subvol and subvolid from mount options - subvol=$(echo "$mount_opts" | grep -oP 'subvol=\K[^,]*') - mount_opts=$(echo "$mount_opts" | sed -e 's/subvol=[^,]*,//g' -e 's/subvolid=[^,]*,//g') - - # Rename device if specified - device="$original_device" - if [[ -n "${rename_map[$device]}" ]]; then - device="${rename_map[$device]}" - fi - - mkdir -p "/mnt/restore$mount_point" - fs_type=$(blkid -o value -s TYPE "$device") - - if [[ "$fs_type" == "btrfs" ]]; then - if [[ -n "$subvol" ]]; then - echo "Mounting Btrfs subvolume $subvol on /mnt/restore$mount_point" - mount -t btrfs -o subvol="$subvol,$mount_opts" "$device" "/mnt/restore$mount_point" - else - echo "Mounting Btrfs volume $device on /mnt/restore$mount_point" - mount -t btrfs -o "$mount_opts" "$device" "/mnt/restore$mount_point" - fi - else - echo "Mounting $device on /mnt/restore$mount_point with options $mount_opts" - mount -o "$mount_opts" "$device" "/mnt/restore$mount_point" - fi - done < "${backupDir}/mount_points.backup" - echo "Mount points restored to /mnt/restore." - else - echo "Backup file ${backupDir}/mount_points.backup not found." - return 1 - fi -} - -# Function to restore a partition table with optional device renaming -restore_partition() { - local device="$1" - local original_device="$device" - local backup_file - local temp_file - - # Check if the device should be renamed - if [[ -n "${rename_map[$device]}" ]]; then - echo "Renaming device $device to ${rename_map[$device]}" - device="${rename_map[$device]}" - fi - - backup_file="${backupDir}/partition_table_$(basename "$original_device").backup" - if [[ ! -f "$backup_file" ]]; then - echo "Backup file $backup_file not found." - return 1 - fi - - # Create a temporary file for the modified backup - temp_file=$(mktemp) - trap 'rm -f "$temp_file"' EXIT - - # Modify the backup file to use the new device name - sed "s|$original_device|$device|g" "$backup_file" > "$temp_file" - - echo "Restoring partition table for $device..." - sfdisk "$device" < "$temp_file" - echo "Partition table restored from $temp_file" -} - -# Function to restore filesystem UUID with optional device renaming -restore_uuid() { - local partition="$1" - local original_partition="$partition" - local uuid - - # Check if the partition should be renamed - if [[ -n "${rename_map[$partition]}" ]]; then - partition="${rename_map[$partition]}" - fi - - if [[ -f "${backupDir}/uuid_$(basename "$original_partition").backup" ]]; then - uuid=$(cut -d'=' -f2 < "${backupDir}/uuid_$(basename "$original_partition").backup" | tr -d '"') - echo "Restoring UUID $uuid to $partition..." - - case "$(blkid -o value -s TYPE "$partition")" in - ext4) - tune2fs -U "$uuid" "$partition" - ;; - xfs) - xfs_admin -U "$uuid" "$partition" - ;; - btrfs) - btrfstune -u "$uuid" "$partition" - ;; - *) - echo "Unsupported filesystem type." - return 1 - ;; - esac - - echo "UUID restored." - else - echo "Backup file ${backupDir}/uuid_$(basename "$original_partition").backup not found." - return 1 - fi -} - -# Function to handle all backup operations -backup_all_partitions() { - echo "Backing up all partitions..." - backup_mount_points - - while IFS= read -r line; do - local device - device=$(echo "$line" | awk '{print $1}') - backup_partition "$device" - backup_uuid "$device" - done < "${backupDir}/mount_points.backup" - - backup_btrfs_subvolumes "/mnt" -} - -# Function to restore all partitions and filesystems from backup files -restore_all() { - echo "Restoring all partitions and filesystems from backup..." - - # Restore partition tables - while IFS= read -r line; do - local device - device=$(echo "$line" | awk '{print $1}') - # Rename device if specified - if [[ -n "${rename_map[$device]}" ]]; then - device="${rename_map[$device]}" - fi - restore_partition "$device" - done < "${backupDir}/mount_points.backup" - - if [[ "$restore_uuid" == true ]]; then - while IFS= read -r line; do - local partition - partition=$(echo "$line" | awk '{print $1}') - # Rename partition if specified - if [[ -n "${rename_map[$partition]}" ]]; then - partition="${rename_map[$partition]}" - fi - restore_uuid "$partition" - done < "${backupDir}/mount_points.backup" - fi - - restore_btrfs_subvolumes "/mnt/restore" -} - -# Main function to handle command-line arguments and invoke appropriate functions -main() { - local exclude_opts=() - local exclude_file - local rename_map=() - local restore_uuid=true - - case "$1" in - backup) - shift - while [[ "$#" -gt 0 ]]; do - case "$1" in - --exclude) - shift - exclude_opts+=("$1") - shift - ;; - --exclude-file) - shift - exclude_file="$1" - if [[ -f "$exclude_file" ]]; then - while IFS= read -r line; do - exclude_opts+=("$line") - done < "$exclude_file" - else - echo "Exclude file $exclude_file does not exist." - exit 1 - fi - shift - ;; - *) - echo "Usage: $0 backup [--exclude ]... [--exclude-file ]" - exit 1 - ;; - esac - done - - create_backup_dir - backup_all_partitions - ;; - - restore) - shift - while [[ "$#" -gt 0 ]]; do - case "$1" in - --no-uuid) - restore_uuid=false - shift - ;; - --exclude) - shift - exclude_opts+=("$1") - shift - ;; - --exclude-file) - shift - exclude_file="$1" - if [[ -f "$exclude_file" ]]; then - while IFS= read -r line; do - exclude_opts+=("$line") - done < "$exclude_file" - else - echo "Exclude file $exclude_file does not exist." - exit 1 - fi - shift - ;; - --rename) - shift - local old_device="$1" - shift - local new_device="$1" - rename_map["$old_device"]="$new_device" - shift - ;; - *) - echo "Usage: $0 restore [--no-uuid] [--exclude ]... [--exclude-file ] [--rename ]" - exit 1 - ;; - esac - done - - restore_all - ;; - - *) - echo "Usage: $0 {backup|restore} [options]" - exit 1 - ;; - esac -} - -# Call the main function with all arguments -main "$@" diff --git a/scripts/partbackup4 b/scripts/partbackup4 deleted file mode 100644 index a73abf3..0000000 --- a/scripts/partbackup4 +++ /dev/null @@ -1,388 +0,0 @@ -#!/bin/bash - -# Global variables for restore directory -restoreDir="/etc/restore" -backupDir="${restoreDir}/data" - -# Internal Variables used globally -declare -a exclude_opts -declare -A rename_map -declare restore_uuid=true - -# Function to create backup directory -create_backup_dir() { - echo "Creating backup directory at ${backupDir}..." - mkdir -p "$backupDir" - echo "Backup directory created." -} - -# Function to backup a partition table -backup_partition() { - local device="$1" - - echo "Backing up partition table for $device..." - sfdisk --dump "$device" > "${backupDir}/partition_table_$(basename "$device").backup" - echo "Partition table backed up to ${backupDir}/partition_table_$(basename "$device").backup" -} - -# Function to backup filesystem UUID -backup_uuid() { - local partition="$1" - - echo "Backing up UUID for $partition..." - blkid "$partition" | awk '{print $2}' > "${backupDir}/uuid_$(basename "$partition").backup" - echo "UUID backed up to ${backupDir}/uuid_$(basename "$partition").backup" -} - -# Function to backup Btrfs subvolumes, excluding snapshots and nested subvolumes -backup_btrfs_subvolumes() { - local mount_point="$1" - local subvol_path - local subvol_name - - echo "Backing up Btrfs subvolumes from $mount_point to ${backupDir}..." - mkdir -p "${backupDir}/btrfs_subvolumes" - btrfs subvolume list -p "$mount_point" | while read -r line; do - subvol_path=$(echo "$line" | awk '{print $NF}') - subvol_name=$(basename "$subvol_path") - - # Skip snapshots and subvolumes under .snapshots - if [[ "$subvol_path" == *.snapshots/* || "$subvol_path" == ".snapshots" ]]; then - continue - fi - - echo "Backing up subvolume $subvol_name" - btrfs subvolume snapshot "$mount_point/$subvol_path" "${backupDir}/btrfs_subvolumes/$subvol_name" - done - echo "Btrfs subvolumes backed up to ${backupDir}/btrfs_subvolumes" -} - -# Function to backup current mount points and options -backup_mount_points() { - local line - local device - - echo "Backing up current mount points and options..." - while IFS= read -r line; do - device=$(echo "$line" | awk '{print $1}') - # Skip excluded devices - if is_excluded "$device"; then - echo "Skipping excluded device $device" - continue - fi - backup_partition "$device" - backup_uuid "$device" - done < <(mount | grep "^/dev") - #mount | grep "^/dev" > "${backupDir}/mount_points.backup" - echo "Mount points backed up to ${backupDir}/mount_points.backup" -} - -# Function to restore Btrfs subvolumes to /mnt/restore, excluding snapshots and nested subvolumes -restore_btrfs_subvolumes() { - local mount_point="$1" - local subvol_snapshot - local subvol_name - - echo "Restoring Btrfs subvolumes from ${backupDir}/btrfs_subvolumes to /mnt/restore/$mount_point..." - mkdir -p "/mnt/restore$mount_point" - for subvol_snapshot in "${backupDir}/btrfs_subvolumes"/*; do - if [[ -d "$subvol_snapshot" ]]; then - subvol_name=$(basename "$subvol_snapshot") - - # Restore subvolume to the mount point - echo "Restoring subvolume $subvol_name" - btrfs subvolume snapshot "$subvol_snapshot" "/mnt/restore$mount_point/$subvol_name" - fi - done - echo "Btrfs subvolumes restored to /mnt/restore$mount_point" -} - -# Function to restore mount points to /mnt/restore, supporting Btrfs subvolumes -restore_mount_points() { - local original_device - local device - local mount_point - local mount_opts - local subvol - local fs_type - - if [[ -f "${backupDir}/mount_points.backup" ]]; then - echo "Restoring mount points from ${backupDir}/mount_points.backup to /mnt/restore..." - mkdir -p /mnt/restore - while IFS= read -r line; do - original_device=$(echo "$line" | awk '{print $1}') - mount_point=$(echo "$line" | awk '{print $3}') - mount_opts=$(echo "$line" | awk -F' ' '{for(i=4;i<=NF;i++){print $i}}' | tr -d '()') - - # Extract and remove subvol and subvolid from mount options - subvol=$(echo "$mount_opts" | grep -oP 'subvol=\K[^,]*') - mount_opts=$(echo "$mount_opts" | sed -e 's/subvol=[^,]*,//g' -e 's/subvolid=[^,]*,//g') - - # Rename device if specified - device="$original_device" - if [[ -n "${rename_map[$device]}" ]]; then - device="${rename_map[$device]}" - fi - - mkdir -p "/mnt/restore$mount_point" - fs_type=$(blkid -o value -s TYPE "$device") - - if [[ "$fs_type" == "btrfs" ]]; then - if [[ -n "$subvol" ]]; then - echo "Mounting Btrfs subvolume $subvol on /mnt/restore$mount_point" - mount -t btrfs -o subvol="$subvol,$mount_opts" "$device" "/mnt/restore$mount_point" - else - echo "Mounting Btrfs volume $device on /mnt/restore$mount_point" - mount -t btrfs -o "$mount_opts" "$device" "/mnt/restore$mount_point" - fi - else - echo "Mounting $device on /mnt/restore$mount_point with options $mount_opts" - mount -o "$mount_opts" "$device" "/mnt/restore$mount_point" - fi - done < "${backupDir}/mount_points.backup" - echo "Mount points restored to /mnt/restore." - else - echo "Backup file ${backupDir}/mount_points.backup not found." - return 1 - fi -} - -# Function to restore a partition table with optional device renaming -restore_partition() { - local device="$1" - local original_device="$device" - local backup_file - local temp_file - - # Check if the device should be renamed - if [[ -n "${rename_map[$device]}" ]]; then - echo "Renaming device $device to ${rename_map[$device]}" - device="${rename_map[$device]}" - fi - - backup_file="${backupDir}/partition_table_$(basename "$original_device").backup" - if [[ ! -f "$backup_file" ]]; then - echo "Backup file $backup_file not found." - return 1 - fi - - # Create a temporary file for the modified backup - temp_file=$(mktemp) - trap 'rm -f "$temp_file"' EXIT - - # Modify the backup file to use the new device name - sed "s|$original_device|$device|g" "$backup_file" > "$temp_file" - - echo "Restoring partition table for $device..." - sfdisk "$device" < "$temp_file" - echo "Partition table restored from $temp_file" -} - -# Function to restore filesystem UUID with optional device renaming -restore_uuid() { - local partition="$1" - local original_partition="$partition" - local uuid - - # Check if the partition should be renamed - if [[ -n "${rename_map[$partition]}" ]]; then - partition="${rename_map[$partition]}" - fi - - if [[ -f "${backupDir}/uuid_$(basename "$original_partition").backup" ]]; then - uuid=$(cut -d'=' -f2 < "${backupDir}/uuid_$(basename "$original_partition").backup" | tr -d '"') - echo "Restoring UUID $uuid to $partition..." - - case "$(blkid -o value -s TYPE "$partition")" in - ext4) - tune2fs -U "$uuid" "$partition" - ;; - xfs) - xfs_admin -U "$uuid" "$partition" - ;; - btrfs) - btrfstune -u "$uuid" "$partition" - ;; - *) - echo "Unsupported filesystem type." - return 1 - ;; - esac - - echo "UUID restored." - else - echo "Backup file ${backupDir}/uuid_$(basename "$original_partition").backup not found." - return 1 - fi -} - -# Function to handle exclusion list with wildcard and reverse matching -is_excluded() { - local pattern="$1" - local device="$2" - - for exclude in "${exclude_opts[@]}"; do - if [[ "$exclude" == !* ]]; then - pattern="${exclude#!}" - if [[ "$device" == $pattern ]]; then - return 1 - fi - else - pattern="$exclude" - if [[ "$device" == $pattern ]]; then - return 0 - fi - fi - done - - return 1 -} - - -# Function to handle all backup operations -backup_all_partitions() { - local device - local mount_point - local fs_type - - echo "Backing up all partitions..." - backup_mount_points - - while IFS= read -r line; do - local device - device=$(echo "$line" | awk '{print $1}') - mount_point=$(echo "$line" | awk '{print $3}') - fs_type=$(echo "$line" | awk '{print $5}') - # Skip excluded devices - if is_excluded "$device"; then - echo "Skipping excluded device $device" - continue - fi - backup_partition "$device" - backup_uuid "$device" - done < "${backupDir}/mount_points.backup" - - backup_btrfs_subvolumes "/mnt" -} - -# Function to restore all partitions and filesystems from backup files -restore_all() { - echo "Restoring all partitions and filesystems from backup..." - - # Restore partition tables - while IFS= read -r line; do - local device - device=$(echo "$line" | awk '{print $1}') - # Rename device if specified - if [[ -n "${rename_map[$device]}" ]]; then - device="${rename_map[$device]}" - fi - restore_partition "$device" - done < "${backupDir}/mount_points.backup" - - if [[ "$restore_uuid" == true ]]; then - while IFS= read -r line; do - local partition - partition=$(echo "$line" | awk '{print $1}') - # Rename partition if specified - if [[ -n "${rename_map[$partition]}" ]]; then - partition="${rename_map[$partition]}" - fi - restore_uuid "$partition" - done < "${backupDir}/mount_points.backup" - fi - - restore_btrfs_subvolumes "/mnt/restore" -} - -# Main function to handle command-line arguments and invoke appropriate functions -main() { - local exclude_file - - case "$1" in - backup) - shift - while [[ "$#" -gt 0 ]]; do - case "$1" in - --exclude) - shift - exclude_opts+=("$1") - shift - ;; - --exclude-file) - shift - exclude_file="$1" - if [[ -f "$exclude_file" ]]; then - while IFS= read -r line; do - exclude_opts+=("$line") - done < "$exclude_file" - else - echo "Exclude file $exclude_file does not exist." - exit 1 - fi - shift - ;; - *) - echo "Usage: $0 backup [--exclude ]... [--exclude-file ]" - exit 1 - ;; - esac - done - - create_backup_dir - backup_all_partitions - ;; - - restore) - shift - while [[ "$#" -gt 0 ]]; do - case "$1" in - --no-uuid) - restore_uuid=false - shift - ;; - --exclude) - shift - exclude_opts+=("$1") - shift - ;; - --exclude-file) - shift - exclude_file="$1" - if [[ -f "$exclude_file" ]]; then - while IFS= read -r line; do - exclude_opts+=("$line") - done < "$exclude_file" - else - echo "Exclude file $exclude_file does not exist." - exit 1 - fi - shift - ;; - --rename) - shift - local old_device="$1" - shift - local new_device="$1" - rename_map["$old_device"]="$new_device" - shift - ;; - *) - echo "Usage: $0 restore [--no-uuid] [--exclude ]... [--exclude-file ] [--rename ]" - exit 1 - ;; - esac - done - - restore_all - ;; - - *) - echo "Usage: $0 {backup|restore} [options]" - exit 1 - ;; - esac -} - -# Call the main function with all arguments -main "$@" diff --git a/scripts/partbackup5 b/scripts/partbackup5 deleted file mode 100755 index 6255161..0000000 --- a/scripts/partbackup5 +++ /dev/null @@ -1,651 +0,0 @@ -#!/bin/bash - -# Global variables for restore directory -restoreDir="/etc/restore" -backupDir="${restoreDir}/data" - -# Internal Variables used globally -declare -a exclude_opts -declare -A rename_map -declare -A btrfs_roots -declare restore_uuid=true -#declare dry_run=false - -# Function to create backup directory -create_backup_dir() { - echo "Creating backup directory at ${backupDir}..." - mkdir -p "$backupDir" || exit_fail 200 "FATAL: Failed to create '$backupDir'" - echo "Backup directory created." -} - -# Function to show command-line help -showHelp() { - echo "Usage: $0 {backup|restore} [options]" - echo - echo "Options:" - echo " --exclude Exclude devices matching the pattern from backup or restore." - echo " --exclude-file Exclude devices listed in the specified file from backup or restore." - echo " --rename Rename a device during the restore process." - echo " --no-uuid Disable restoring of UUIDs during restore." - echo " --help Show this help message and exit." - echo - echo "Commands:" - echo " backup Perform backup of all partitions, UUIDs, and Btrfs subvolumes." - echo " restore Restore all partitions, UUIDs, and Btrfs subvolumes from backup." - echo - echo "Examples:" - echo " $0 backup --exclude /dev/sda1" - echo " $0 restore --rename /dev/sda /dev/sdb" - echo -} - -# Function to run commands based on dry-run mode -#run_command() { -# if [[ "$dry_run" == true ]]; then -# echo "[DRY-RUN] $@" -# else -# "$@" -# fi -#} - -echoerr() { - echo "$*" 1>&2 -} - -exit_fail() { - local rc=$1 - shift - - echoerr "$*" - exit "$rc" -} - -get_base_device() { - local partition=$1 - local devnode basenode - - if [[ -b "$partition" ]]; then - # Remove partition suffix (p2, 2, etc.) but keep the rest of the device name - devnode=$(basename "$partition") - if [[ -s "/sys/class/block/$devnode" ]]; then - basenode=$(basename "$(readlink -f "/sys/class/block/$devnode/..")") - echo "/dev/$basenode" - else - echo "$partition" | sed -E 's/(p[0-9]+|[0-9]+)$//' - fi - else - return 1 - fi -} - -check_in_array() { - local e match="$1" - shift - - for e; do - [[ "$e" == "$match" ]] && return 0 - done - - return 1 -} - -# Function to backup a partition table -backup_partition() { - local device="$1" - local rc=0 - - echo "Backing up partition table for $device..." - sfdisk --dump "$device" > "${backupDir}/partitions_$(basename "$device").backup" || rc=$? - echo "Partition table backed up to ${backupDir}/partitions_$(basename "$device").backup" - - return "$rc" -} - -# Function to backup filesystem UUID -backup_uuid() { - local partition="$1" - - echo "Backing up UUID for $partition..." - blkid -o value -s UUID "$partition" > "${backupDir}/uuid_$(basename "$partition").backup" - echo "UUID backed up to ${backupDir}/uuid_$(basename "$partition").backup" -} - -# Function to backup Btrfs subvolumes, excluding snapshots and nested subvolumes -backup_btrfs_subvolumes() { - local partition="$1" - local mount_point="$2" - local subvol_path - #local parent_id - local backup_file - local results - - echo "Backing up list of Btrfs subvolumes from $mount_point..." - backup_file="${backupDir}/btrfs_$(basename "$partition").backup" - mkdir -p "${backupDir}" - - # Initialize results variable - results="" - - while read -r line; do - subvol_path=$(echo "$line" | awk '{print $NF}') - #parent_id=$(echo "$line" | awk '{print $6}') - - # Skip subvolumes that do not have parent ID 5 - #if [[ "$parent_id" -ne 5 ]]; then - # continue - #fi - - # Skip .snapshots and subvolumes under .snapshots - if [[ "$subvol_path" == ".snapshots" || "$subvol_path" == .snapshots/* ]]; then - continue - fi - - # Skip @snapshots and subvolumes under @snapshots - if [[ "$subvol_path" == "@snapshots" || "$subvol_path" == @snapshots/* ]]; then - continue - fi - - # Skip .veeam_snapshots - if [[ "$subvol_path" == ".veeam_snapshots" || "$subvol_path" == .veeam_snapshots/* ]]; then - continue - fi - - # Append valid subvolume path to results - results+="$subvol_path"$'\n' - done < <(btrfs subvolume list -p "$mount_point" | grep "parent 5") - - # Write results to the backup file - echo "$results" > "$backup_file" - - echo "List of Btrfs subvolumes backed up to $backup_file" -} - -# Function to backup current mount points and options -backup_mounts() { - local line - local device - local mount_point - local fs_type - local results - - # Initialize results variable - results="" - - echo "Backing up current mount points and options..." - while IFS= read -r line; do - if [[ -z "$line" ]]; then - continue - fi - device=$(echo "$line" | awk '{print $1}') - mount_point=$(echo "$line" | awk '{print $3}') - fs_type=$(echo "$line" | awk '{print $5}') - - # Skip excluded devices - if is_excluded "$device"; then - echo "Skipping excluded device $device" - continue - fi - - if [[ -z "${btrfs_roots["$device"]}" ]]; then - if [[ "$fs_type" == "btrfs" ]]; then - # Keep track of initial unique btrfs mounts per device - btrfs_roots["$device"]="$mount_point" - fi - - # Update backups accordingly for the rest - #results+="$line"$'\n' - #backup_partition "$device" - #backup_uuid "$device" - fi - results+="$line"$'\n' - done < <(mount | grep "^/dev") - #mount | grep "^/dev" > "${backupDir}/mounts.backup" - - # Write results to the backup file - echo "$results" > "${backupDir}/mounts.backup" - - echo "Mount points backed up to ${backupDir}/mounts.backup" -} - -# Function to restore mount points to /mnt/restore, supporting Btrfs subvolumes -restore_mount_points() { - local original_partition - local partition - local mount_point - local mount_opts - local subvol - local fs_type - - if [[ -f "${backupDir}/mounts.backup" ]]; then - echo "Restoring mount points from ${backupDir}/mounts.backup to /mnt/restore..." - mkdir -p /mnt/restore - while IFS= read -r line; do - original_partition=$(echo "$line" | awk '{print $1}') - mount_point=$(echo "$line" | awk '{print $3}') - mount_opts=$(echo "$line" | awk -F' ' '{for(i=4;i<=NF;i++){print $i}}' | tr -d '()') - - # Extract and remove subvol and subvolid from mount options - subvol=$(echo "$mount_opts" | grep -oP 'subvol=\K[^,]*') - mount_opts=$(echo "$mount_opts" | sed -e 's/subvol=[^,]*,//g' -e 's/subvolid=[^,]*,//g') - - # Rename partition if specified - partition="$original_partition" - if [[ -n "${rename_map[$partition]}" ]]; then - partition="${rename_map[$partition]}" - echo "Renaming '$original_partition' to '$partition'" - fi - - mkdir -p "/mnt/restore$mount_point" - fs_type=$(blkid -o value -s TYPE "$partition") - - if [[ "$fs_type" == "btrfs" ]]; then - if [[ -n "$subvol" ]]; then - echo "Mounting Btrfs subvolume $subvol on /mnt/restore$mount_point" - mount -t btrfs -o subvol="$subvol,$mount_opts" "$partition" "/mnt/restore$mount_point" - else - echo "Mounting Btrfs volume $partition on /mnt/restore$mount_point" - mount -t btrfs -o "$mount_opts" "$partition" "/mnt/restore$mount_point" - fi - else - echo "Mounting $partition on /mnt/restore$mount_point with options $mount_opts" - mount -o "$mount_opts" "$partition" "/mnt/restore$mount_point" - fi - done < "${backupDir}/mounts.backup" - echo "Mount points restored to /mnt/restore." - else - echo "Backup file ${backupDir}/mounts.backup not found." - return 1 - fi -} - -# Function to restore a partition table with optional device renaming -restore_partition() { - local device="$1" - local original_device="$device" - local backup_file - local temp_file - #local mount_point - - # Check if the device should be renamed - if [[ -n "${rename_map[$device]}" ]]; then - echo "Renaming device $device to ${rename_map[$device]}" - device="${rename_map[$device]}" - fi - - backup_file="${backupDir}/partitions_$(basename "$original_device").backup" - if [[ ! -f "$backup_file" ]]; then - echo "Backup file $backup_file not found." - return 1 - fi - - # Create a temporary file for the modified backup - temp_file=$(mktemp) - trap 'rm -f "$temp_file"' EXIT - - # Modify the backup file to use the new device name - sed "s|$original_device|$device|g" "$backup_file" > "$temp_file" - - echo "Restoring partition table for $device..." - sfdisk "$device" < "$temp_file" - echo "Partition table restored from $backup_file" - - # Check if the filesystem is Btrfs - #if blkid -o value -s TYPE "$device" | grep -q "btrfs"; then - # mount_point="/mnt/restore$(blkid -o value -s UUID "$device")" - # mkdir -p "$mount_point" - # mount -t btrfs "$device" "$mount_point" - # - # # Restore Btrfs subvolumes for the device - # restore_btrfs_subvolumes "$device" "$mount_point" - # - # umount "$mount_point" - # rmdir "$mount_point" - #fi -} - -# Function to restore filesystem UUID with optional device renaming -restore_uuid() { - local partition="$1" - local original_partition="$partition" - local uuid - - # Check if the partition should be renamed - if [[ -n "${rename_map[$partition]}" ]]; then - partition="${rename_map[$partition]}" - fi - - if [[ -f "${backupDir}/uuid_$(basename "$original_partition").backup" ]]; then - uuid=$(<"${backupDir}/uuid_$(basename "$original_partition").backup") - #uuid=$(cut -d'=' -f2 < "${backupDir}/uuid_$(basename "$original_partition").backup" | tr -d '"') - echo "Restoring UUID $uuid to $partition..." - - case "$(blkid -o value -s TYPE "$partition")" in - ext2|ext3|ext4) - tune2fs -U "$uuid" "$partition" - ;; - xfs) - xfs_admin -U "$uuid" "$partition" - ;; - btrfs) - btrfstune -u "$uuid" "$partition" - ;; - *) - echo "Unsupported filesystem type." - return 1 - ;; - esac - - echo "UUID restored." - else - echo "Backup file ${backupDir}/uuid_$(basename "$original_partition").backup not found." - return 1 - fi -} - -# Function to restore Btrfs subvolumes from the backup list to the given mount point -restore_btrfs_subvolumes() { - local partition="$1" - local original_partition="$partition" - local mount_point - local subvol_path - local backup_file - - # Check if the partition should be renamed - if [[ -n "${rename_map[$partition]}" ]]; then - partition="${rename_map[$partition]}" - fi - - backup_file="${backupDir}/btrfs_$(basename "$original_partition").backup" - - echo "Restoring Btrfs subvolumes from $backup_file to $partition..." - - if [[ ! -f "$backup_file" ]]; then - echo "Backup file $backup_file not found." - return 1 - fi - - #mount_point="/mnt/restore_btrfs" - mount_point="/mnt/restore_$(blkid -o value -s UUID "$partition")" - mkdir -p "$mount_point" || exit_fail 200 "FATAL: Cannot mkdir '$mount_point'" - mount -t btrfs "$partition" "$mount_point" || exit_fail 201 "FATAL: Cannot mount btrfs filesystem '$partition' to '$mount_point'" - - while IFS= read -r subvol_path; do - echo "Restoring subvolume $subvol_path" - btrfs subvolume create "$mount_point/$subvol_path" || exit_fail 202 "FATAL: Cannot create subvolume '$subvol_path' on '$mount_point'" - done < "$backup_file" - - umount "$mount_point" - rmdir "$mount_point" - - echo "Btrfs subvolumes restored on $partition" -} - -# Format device/partition -restore_format() { - local partition="$1" - local fs_type="$2" - - if [[ ! -b "$partition" ]]; then - echoerr "Partition '$partition' is not a block device, cannot format" - return 1 - fi - - case "$fs_type" in - ext2|ext3|ext4) - mkfs."$fs_type" "$partition" - ;; - xfs) - mkfs.xfs -f "$partition" - ;; - btrfs) - mkfs.btrfs -f "$partition" - ;; - vfat) - mkfs.vfat "$partition" - ;; - *) - echo "Unsupported filesystem type." - return 1 - ;; - esac -} - -# Function to handle exclusion list with wildcard and reverse matching -is_excluded() { - #local pattern="$" - local device="$1" - - for exclude in "${exclude_opts[@]}"; do - if [[ "$exclude" == !* ]]; then - pattern="${exclude#!}" - if [[ "$device" == $pattern ]]; then - return 1 - fi - else - pattern="$exclude" - if [[ "$device" == $pattern ]]; then - return 0 - fi - fi - done - - return 1 -} - - -# Function to handle all backup operations -backup_all() { - local partition - local base_device - local mount_point - local fs_type - local -a device_nodes - - echo "Backing up all partitions..." - backup_mounts - - while IFS= read -r line; do - partition=$(echo "$line" | awk '{print $1}') - mount_point=$(echo "$line" | awk '{print $3}') - fs_type=$(echo "$line" | awk '{print $5}') - if [[ -z "$line" || -z "$partition" || -z "$mount_point" || -z "$fs_type" ]]; then - continue - fi - - # Skip excluded partition - if is_excluded "$partition"; then - echo "Skipping excluded device $partition" - continue - fi - - if ! check_in_array "$partition" "${device_nodes[@]}"; then - device_nodes+=("$partition") - base_device=$(get_base_device "$partition") - - if ! check_in_array "$base_device" "${device_nodes[@]}"; then - device_nodes+=("$base_device") - backup_partition "$base_device" - fi - - backup_uuid "$partition" - - # If the filesystem type is Btrfs, back up its subvolumes - if [[ "$fs_type" == "btrfs" ]]; then - backup_btrfs_subvolumes "$partition" "$mount_point" - fi - fi - done < "${backupDir}/mounts.backup" -} - -# Function to restore all partitions and filesystems from backup files -restore_all() { - local device - local original_device="$device" - local mount_point - local fs_type - local -a device_nodes - #local partition - - echo "Restoring all partitions and filesystems from backup..." - - # Restore partition tables - while IFS= read -r line; do - device=$(echo "$line" | awk '{print $1}') - mount_point=$(echo "$line" | awk '{print $3}') - fs_type=$(echo "$line" | awk '{print $5}') - if [[ -z "$line" || -z "$device" || -z "$mount_point" || -z "$fs_type" ]]; then - continue - fi - - # Skip excluded partition - if is_excluded "$device"; then - echo "Skipping excluded device $device" - continue - fi - - # Rename device if specified - if [[ -n "${rename_map[$device]}" ]]; then - device="${rename_map[$device]}" - echo "Renaming device '$original_device' to '$device'" - fi - - if ! check_in_array "$device" "${device_nodes[@]}"; then - device_nodes+=("$device") - - restore_partition "$original_device" - restore_format "$device" "$fs_type" - - if [[ "$restore_uuid" == true ]]; then - restore_uuid "$original_device" - fi - - if [[ "$fs_type" == "btrfs" ]]; then - if [[ -z "${btrfs_roots["$device"]}" ]]; then - # Keep track of initial unique btrfs mounts per device - btrfs_roots["$device"]="$mount_point" - restore_btrfs_subvolumes "$original_device" - fi - fi - fi - done < "${backupDir}/mounts.backup" - - #if [[ "$restore_uuid" == true ]]; then - # while IFS= read -r line; do - # partition=$(echo "$line" | awk '{print $1}') - # # Rename partition if specified - # if [[ -n "${rename_map[$partition]}" ]]; then - # partition="${rename_map[$partition]}" - # fi - # restore_uuid "$partition" - # done < "${backupDir}/mounts.backup" - #fi -} - -# Main function to handle command-line arguments and invoke appropriate functions -main() { - local exclude_file - local old_device new_device - - if [[ "$1" == "--help" ]]; then - showHelp - exit 0 - fi - - case "$1" in - backup) - shift - while [[ "$#" -gt 0 ]]; do - case "$1" in - --exclude) - shift - exclude_opts+=("$1") - shift - ;; - --exclude-file) - shift - exclude_file="$1" - if [[ -f "$exclude_file" ]]; then - while IFS= read -r line; do - exclude_opts+=("$line") - done < "$exclude_file" - else - echo "Exclude file $exclude_file does not exist." - exit 1 - fi - shift - ;; - --help) - showHelp - exit 0 - ;; - *) - echo "Invalid option: $1" - echo "Use --help to display the help message." - exit 1 - ;; - esac - done - - create_backup_dir - backup_all - ;; - - restore) - shift - while [[ "$#" -gt 0 ]]; do - case "$1" in - --no-uuid) - restore_uuid=false - shift - ;; - --exclude) - shift - exclude_opts+=("$1") - shift - ;; - --exclude-file) - shift - exclude_file="$1" - if [[ -f "$exclude_file" ]]; then - while IFS= read -r line; do - exclude_opts+=("$line") - done < "$exclude_file" - else - echo "Exclude file $exclude_file does not exist." - exit 1 - fi - shift - ;; - --rename) - shift - old_device="$1" - shift - new_device="$1" - rename_map["$old_device"]="$new_device" - shift - ;; - --help) - showHelp - exit 0 - ;; - *) - echo "Invalid option: $1" - echo "Use --help to display the help message." - exit 1 - ;; - esac - done - - restore_all - ;; - - *) - echo "Invalid command: $1" - echo "Use --help to display the help message." - exit 1 - ;; - esac -} - -# Call the main function with all arguments -main "$@"