diff --git a/Okiru b/Okiru new file mode 100755 index 0000000..a4b9a54 --- /dev/null +++ b/Okiru @@ -0,0 +1,131 @@ +#!/bin/bash +##This script is a helper script defining universal functions to be used in other scripts - +#+namely logging levels and locations and error reporting. +#+The idea is to source it in other scripts and thus have them all log the same. + +#Error array for scripts that report runtime errors +declare -a errors=() + +#Function to create inital log; Accepts the prefix of the log and folder. +#+For example, passing logging testytest will create the folder /home/shmick/Scripts/Logs/testytest +#+As well as a log file named testytest_Log and a report named testytest_[script_run_time] +#+Ex: /home/shmick/Scripts/Logs/testytest/testytest. +#+These files can then be pulled, renamed and compressed on an Ansible node. + +#Color output# +BLACK='\033[0;30m' +DARK_GRAY='\033[1;30m' +RED='\033[0;31m' +LIGHT_RED='\033[1;31m' +GREEN='\033[0;32m' +LIGHT_GREEN='\033[1;32m' +ORANGE='\033[0;33m' +YELLOW='\033[1;33m' +BLUE='\033[0;34m' +LIGHT_BLUE='\033[1;34m' +PURPLE='\033[0;35m' +PURPLE='\033[1;35m' +CYAN='\033[0;36m' +LIGHT_CYAN='\033[1;36m' +WHITE='\033[0;37m' +GRAY='\033[1;37m' +STOP="\e[0m" + + +#If a function calls 'logging' for a log, it will create a log file; otherwise, keep the +#+variable empty thus printing only to terminal +logging () { + if [[ -n $2 ]]; then + if [[ ! -d "/home/shmick/Scripts/Logs/$1/" ]]; then + mkdir -p "/home/shmick/Scripts/Logs/$1/" + fi + export LOG="/home/shmick/Scripts/Logs/$1/$2Log" + export REPORT="/home/shmick/Scripts/Logs/$1/$2" + export PREFIX=$2 + else + if [[ ! -d "/home/shmick/Scripts/Logs/$1/" ]]; then + mkdir -p "/home/shmick/Scripts/Logs/$1/" + fi + export LOG="/home/shmick/Scripts/Logs/$1/$1Log" + export REPORT="/home/shmick/Scripts/Logs/$1/$1" + export PREFIX=$1 + fi + ls $LOG + if [[ -f "$LOG" ]]; then + OLD_LOG_DATE=$(stat $LOG | grep Modify | awk '{print $2}' | sed -e 's/-//g') + OLD_LOG_TIME=$(stat $LOG | grep Modify | awk '{print $3}' | sed -e 's/://g' | awk -F. '{print $1}') + mv "$LOG" "$(dirname $LOG)/$(basename $LOG)_"$OLD_LOG_DATE"_"$OLD_LOG_TIME"" 2> /dev/null + zstd -11 --rm -f "$(dirname $LOG)/$(basename $LOG)_"$OLD_LOG_DATE"_"$OLD_LOG_TIME"" > /dev/null +# ^ Append timestamp (YYYYMMDD_HHMMSS - ex 20210301_093543) to log if it exists + fi + touch $LOG + touch $REPORT +#Greeter + if [[ -n "$1" ]]; then + printf "Logging is ${GREEN}enabled${STOP} via Okiru!\n" + printf "Using prefix: ${PURPLE}$PREFIX\n${STOP}" + printf "Logging to directory: ${LIGHT_CYAN}/home/shmick/Scripts/Logs/${PURPLE}$1${LIGHT_CYAN}/\n${STOP}" + printf "Log file: ${LIGHT_CYAN}$LOG\n${STOP}" + printf "Report file: ${LIGHT_CYAN}$REPORT\n${STOP}" + elif [[ -z $1 ]]; then + printf "Logging is ${RED}disabled${STOP}; No log file will be generated.\n" + fi +} +#Debugging level logging; can be toggled via a switch +debug () { + printf "${BLUE}[DEBUG]: $1${STOP}\n" > /dev/stdout + if [[ -f $LOG ]]; then + echo -e "$(date | awk '{print $4}') [DEBUG]: $1" >> $LOG + fi +} +#Information level logging; +info () { + printf "${CYAN}[INFO]:${STOP} $1\n" > /dev/stdout + if [[ -f $LOG ]]; then + echo -e "$(date | awk '{print $4}') [INFO]: $1" >> $LOG + fi +} +#Warning level logging; +warn () { + printf "${YELLOW}[WARNING]:${STOP} $1\n" > /dev/stdout + if [[ -f $LOG ]]; then + echo -e "$(date | awk '{print $4}') [WARN]: $1" >> $LOG + fi +} +#Error logging function; Errors are added to an array and a report file. +error () { + echo $1 1>&2 +# ` ^ Output error message to stderr + printf "${RED}[ERROR]: $1${STOP}\n" > /dev/stdout +# ^ Print it to the screen + errors+=("$1") +# ^ And add to errors array + if [[ -f $LOG ]]; then + echo -e "$(date | awk '{print $4}') [ERROR]: $1" >> $LOG +# ^ Log it with its' time and date + fi + if [[ -f $REPORT ]]; then + echo -e "$1" >> $REPORT +# ^ And without time and date to a report file + fi + return 1 +} +ok () { + printf "${GREEN}[SUCCESS]: $1${STOP}\n" > /dev/stdout + if [[ -f $LOG ]]; then + echo -e "$(date | awk '{print $4}') [SUCCESS]: $1" >> $LOG + fi +} + +#Lock function; accepts the lockfile and the command +lock () { + while [[ -e $1 ]]; do + printf "${RED}[ERROR]:${STOP} Process already running.\n" + break +# ^ Skips whatever is running and moves on + done + if [[ ! -e $1 ]]; then + flock -n $1 $2 + rm -rf $1 + fi +} diff --git a/Resticer.sh b/Resticer.sh new file mode 100755 index 0000000..1fac805 --- /dev/null +++ b/Resticer.sh @@ -0,0 +1,49 @@ +#!/bin/bash +##Simple script to run Restic backups +source /etc/zsh/zprofile > /dev/null 2>&1 +source /home/shmick/Scripts/Okiru +logging Restic + +#Safety function; accepts repository to check +safety(){ +#Check no other Restic process is using this repository; Free unnecessary locks, if present +if [[ -n $(ps aux | grep restic | grep $1) ]]; then + warn "Repository $1 is in use - ignoring" + return 1 +# ^ If there's a restic process holding the repository, leave it alone. +else + info "Repository $1 is not in use - unlocking" + restic -r b2:$1 unlock +# ^ If a lock exists but no process, the repository is safe and should be unlocked. +fi +} +#Backup function; accepts repository and path to backup +backup(){ +#Check safety +if safety $1; then + #Run the backup + if restic -r b2:$1 backup $2; then + ok "Path $2 completed upload to $1." #Running integrity check" + #Run integrity check +# if restic -r b2:$1 check; then +# echo "[OK]: Repository $1 is healthy" + # Prune repository to avoid unnecessary data + if restic -r b2:$1 prune; then + ok "Repository $1 is trim" + else + error "Failed to prune repository $1!" + fi +# else +# echo "[ERR]: Repository $1 failed integrity check!" > /dev/stderr +# fi + else + error "Repository $1 failed to upload path $2!" + fi +fi +} +#Pictures +backup Gerbil-TK /Red-Vol/Media/Pictures/ +#Containers +backup Pukeko-XYZ-Containers /Red-Vol/Media/Containers +#Cloud +backup Pukeko-XYZ-Cloud /Red-Vol/Media/Cloud/Syncthing