Compare commits

1 Commits
Author SHA1 Message Date
hattoben 6c034255b9 Added backup_drive script to make linux backups easy 2026-07-17 14:49:52 -04:00
2 changed files with 278 additions and 0 deletions
+1
View File
@@ -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<br>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||
+277
View File
@@ -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