From 6c034255b932acfe34ca6e1aab0f6bb70e3045ed Mon Sep 17 00:00:00 2001 From: hattoben Date: Fri, 17 Jul 2026 14:49:52 -0400 Subject: [PATCH] Added backup_drive script to make linux backups easy --- README.md | 1 + backup_drive.sh | 277 ++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 278 insertions(+) create mode 100644 backup_drive.sh diff --git a/README.md b/README.md index fdc3bb2..8d18202 100644 --- a/README.md +++ b/README.md @@ -38,3 +38,4 @@ Erasure Environment|Setup Alpine Linux Environment with SquashFS/No Persistence| |User Authentication|Implement user authentication|For Auditing, Logging, connection to network shares, etc.|Yes|Probably kerb auth via krb5 |Logging|Implement logging|For auditing purposes|Yes|Record user, drive serial, grab user list (if windows/unix drive), grab hostname, record script inputs| |Ticket Notes|Add ticket note through script|To keep keyword searchable records associated with a ticket|No|Send email to Otobo with small details such as level, hostname, serial, etc
Might involve policy changes for when a ticket should be created.| +|Back Up Linux Machines|Create a script to back up Linux filesystems|To simplify backing up Linux machines and align Linux backup simplicity with Windows backup simplicity|Yes|| \ No newline at end of file diff --git a/backup_drive.sh b/backup_drive.sh new file mode 100644 index 0000000..363ecdd --- /dev/null +++ b/backup_drive.sh @@ -0,0 +1,277 @@ +#!/bin/bash +#!/usr/bin/env bash + +start_time="$(date '+%Y-%m-%d_%H.%M.%S')" +logdir=/tmp +log="$logdir"/log_"$start_time".log +log_x="$logdir"/log_x_"$start_time".log +exec 3>&1 1>>"$log_x" 2>&1 +set -x + +loginput() { + echo "$*" >&3; + echo "[INPUT] $(date '+%H:%M:%S') $*" >> "$log"; +} + +logresponse() { + echo "[RESPONSE] $(date '+%H:%M:%S') $*" >> "$log"; +} + +loginfo() { + echo "$*" >&3; + echo "[INFO] $(date '+%H:%M:%S') $*" >> "$log"; +} + +logwarn() { + echo "$*" >&3; + echo "[WARNING] $(date '+%H:%M:%S') $*" >> "$log"; +} + +logerror() { + echo "$*" >&3; + echo "[ERROR] $(date '+%H:%M:%S') $*" >> "$log"; +} + +confirm_message () { + local typed= + while [[ ! $typed = "$2" ]]; + do + loginput "$1" + read -r typed + logresponse "$typed" + done +} + +# shellcheck disable=SC2329 +catch_sigint () { + logwarn "Signal Interrupt initiated. Stopping script." + cleanup + kill -INT "$$" +} + +# shellcheck disable=SC2329 +catch_exit () { + cleanup + kill -INT "$$" +} + +# shellcheck disable=SC2329 +cleanup () { + loginfo "Cleaning up." + pcie_disable + loginfo "Unmounting drives." + exec 1>/dev/null 2>&1 + umount /mnt/"$ticket_number" + umount "/mnt/dest" + trap - EXIT + trap - INT +} + +trap catch_sigint SIGINT +trap catch_exit EXIT + +get_netid () { + netid= + while [[ $netid =~ ^\s*$ ]]; + do + loginput "Please enter your r-account netid: " + read -r netid + logresponse "$netid" + if [[ $netid =~ ^\s*$ ]]; + then + logwarn "Your netid cannot be blank." + else + local ret_value=$(kinit "$netid"@EGR.MSU.EDU >&3; echo $?) + if [[ ! $ret_value = "0" ]] + then + kdestroy + netid= + logwarn "Error when authenticating netid $netid." + else + clear + loginfo "Authenticated as user $netid." + fi + fi + done +} + +get_ticket () { + ticket_number= + + loginfo "Please enter the ticket number that corresponds to this backup." + loginfo "Allowed characters: 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, -, _" + loginfo "Examples: 12345, 12345-1, 12345_2" + + loginput "Ticket number: " + read -r ticket_number + logresponse "$ticket_number" + if [[ $ticket_number =~ ^\s*$ ]]; + then + ticket_number="UNKNWN" + logwarn "Starting with no ticket number specified." + logwarn "Backup will be stored under $ticket_number." + fi +} + +mount_remote () { + mkdir -p /mnt/dest + if mount -t cifs -o user="$netid",sec=krb5i "//reinstallbackups/reinstallbackups" /mnt/dest + then + while [ -d /mnt/dest/"$ticket_number" ]; + do + logwarn "Backup directory /mnt/dest/$ticket_number already exists." + loginput "Enter another ticket number: " + read -r ticket_number + logresponse "$ticket_number" + if [[ $ticket_number =~ ^\s*$ ]]; + then + ticket_number="UNKNWN" + logwarn "Starting with no ticket number specified." + logwarn "Backup will be stored under $ticket_number." + fi + done + if ! mkdir -p /mnt/dest/"$ticket_number"; then + logerror "Insufficient permissions to write in //reinstallbackups/reinstallbackups" + exit + else + logdir=/mnt/dest/"$ticket_number" + cp "$log" "$logdir"/log_"$ticket_number"_"$start_time".log + cp "$log_x" "$logdir"/log_x_"$ticket_number"_"$start_time".log + log="$logdir"/log_"$ticket_number"_"$start_time".log + log_x="$logdir"/log_x_"$ticket_number"_"$start_time".log + exec 1>>"$log_x" 2>&1 + set -x + fi + else + logerror "Failed to mount remote DECS drive. Stopping" + exit + fi +} + +get_partition () { + partition= + echo "- - -" | sudo tee /sys/class/scsi_host/host*/scan >/dev/null + echo 1 | sudo tee /sys/class/block/sd?/device/rescan >/dev/null + pcie_enable + echo 1 | sudo tee /sys/class/block/nvme?/device/rescan >/dev/null + + loginfo "Listing current attached devices and partitions..." + loginfo "" + loginfo "$(lsblk -o NAME,SIZE,FSTYPE,LABEL,MODEL,VENDOR | grep -E '^NAME|sd[a-z]|nvme[0-9]')" + loginfo "" + loginput "Which partition would you like to back up? (Type 'help' for help.)" + + while [[ $partition =~ ^\s*$ ]]; + do + read -r partition + logresponse "$partition" + while [[ ! $partition =~ ^sd[a-z][0-9]+$ ]] && [[ ! $partition =~ ^nvme[0-9]n[0-9]p[0-9]+$ ]]; + do + if [[ $partition = "help" ]]; + then + loginfo "The UNIX filesystem thinks of storage devices as directories, which are under /dev/" + loginfo "Partitions are numbered entries beneath a device." + loginfo "If you have a SATA connection, you will be looking for sd{a-z}{1-9}. (i.e. sda1)" + loginfo "If you have a NVME connection, you will be looking for nvme0n1p{1-9}. (i.e. nvme0n1p2)" + else + logwarn "Invalid format, partition should follow naming conventions. (i.e. sd{a-z}{1-9}, nvme0n1p{1-9})" + fi + read -r partition + logresponse "$partition" + done + + if [ -e /dev/"$partition" ]; + then + loginfo "Picking partition /dev/$partition." + else + logwarn "/dev/$partition does not exist, please ensure you are typing the partition name correctly." + partition= + fi + done +} + +backup_partition () { + loginfo "Mounting /dev/$partition read-only." + mkdir -p /mnt/"$ticket_number" + if ! mount -o ro /dev/"$partition" /mnt/"$ticket_number" + then + logerror "Failed to mount /dev/$partition. Stopping" + exit + fi + + local destination=/mnt/dest/"$ticket_number"/"$partition" + if ! mkdir -p "$destination"; then + logerror "Insufficient permissions to write in $destination" + umount /mnt/"$ticket_number" + exit + fi + + loginfo "Backing up /dev/$partition to $destination." + loginfo "This may take a while!" + + local ret_value=$(rsync -avxzSHPL --progress /mnt/"$ticket_number"/ "$destination"/ >&3; echo $?) + if [[ ! $ret_value = "0" ]] + then + case $ret_value in + "23") + logwarn "Rsync finished but some files could not be transferred. Check the log for details." + ;; + + "24") + logwarn "Rsync finished but some files vanished during transfer. Check the log for details." + ;; + + *) + logerror "Rsync failed with exit code $ret_value. Please contact your supervisor." + umount /mnt/"$ticket_number" + exit + ;; + esac + else + loginfo "Finished backing up /dev/$partition to $destination." + fi + + umount /mnt/"$ticket_number" +} + +#Rescan for PCIe devices +pcie_enable (){ + echo 1 > /sys/bus/pci/rescan + loginfo "Enabled PCIe card, sleeping for 5 seconds." + sleep 5 +} + +#Remove the PCIe NVMe readrer +# shellcheck disable=SC2329 +pcie_disable (){ + echo 1 > /sys/bus/pci/devices/0000:02:00.0/remove + echo 1 > /sys/bus/pci/devices/0000:03:00.0/remove + loginfo "Disabled PCIe card." +} + +main (){ + get_netid + loginfo "" + + get_ticket + loginfo "" + + mount_remote + loginfo "" + + get_partition #sets $partition to one of the /dev/xyz partitions. + loginfo "" + + loginfo "Starting process for backing up $partition to /mnt/dest/$ticket_number." + confirm_message "Please type 'confirm' to begin." "confirm" + loginfo "" + + backup_partition + loginfo "" + loginfo "Finished backing up $partition to /mnt/dest/$ticket_number." + loginfo "" + + cleanup +} + +main