jina verze
This commit is contained in:
@@ -0,0 +1,370 @@
|
||||
storageLabel="[Storage]"
|
||||
|
||||
# Lists all backup directories on external storage with type labels (archive, daily, or unknown).
|
||||
function cmdStorageBackupList() {
|
||||
local dirList error dirCount archiveList dailyList
|
||||
run dirList error storageFileList "/" d || { printDanger "$error"; return 1; }
|
||||
dirCount=$(grep -c . <<< "$dirList" || true)
|
||||
archiveList=$(printf '%s\n' "$dirList" | grep -E -- "$backupArchiveDirPattern" | sort || true)
|
||||
dailyList=$(printf '%s\n' "$dirList" | grep -E -- "$backupDailyDirPattern" | sort || true)
|
||||
|
||||
printRow
|
||||
|
||||
local i=0 num dir label
|
||||
while read -r dir; do
|
||||
((++i))
|
||||
num=$(printf "%0${#dirCount}d" "$i")
|
||||
label="$num: $fontBlue$dir$fontReset"
|
||||
|
||||
if listContains "$dir" "$archiveList"; then
|
||||
printDotText "$label" "${fontGreen}archive$fontReset"
|
||||
elif listContains "$dir" "$dailyList"; then
|
||||
printDotText "$label" "${fontGreen}daily$fontReset"
|
||||
else
|
||||
printDotText "$label" "$labelUnknown"
|
||||
fi
|
||||
done < <(awk 'NF' <<< "$dirList")
|
||||
|
||||
printRow
|
||||
}
|
||||
|
||||
# Rotates archive backups on external storage: deletes old entries exceeding $storageArchiveKeep.
|
||||
function cmdStorageBackupArchiveDispatch() {
|
||||
local dirList error
|
||||
run dirList error storageFileList "/" d || { printDanger "$error"; return 1; }
|
||||
|
||||
printSection "Config"
|
||||
printDotText "Type" "$storageType"
|
||||
printDotText "Path" "$rsyncPath"
|
||||
printDotText "Archive keep" "$storageArchiveKeep"
|
||||
printDotText "Archive pattern" "$backupArchiveDirPattern"
|
||||
|
||||
printSection "Directories found"
|
||||
archiveList=$(printf '%s\n' "$dirList" | grep -E -- "$backupArchiveDirPattern" | sort || true)
|
||||
local archiveCount archiveRemoveCount i=0 num label dirDate dirDays archiveRemoveList=""
|
||||
archiveCount=$(grep -c . <<< "$archiveList" || true)
|
||||
if [[ "$archiveCount" -gt 0 ]]; then
|
||||
while read -r dir; do
|
||||
((++i))
|
||||
num=$(printf "%0${#archiveCount}d" "$i")
|
||||
label="$num: $fontBlue$dir$fontReset"
|
||||
|
||||
if (( archiveCount - storageArchiveKeep >= i )); then
|
||||
printDotText "$label" "${fontRed}delete$fontReset"
|
||||
archiveRemoveList+=$'\n'"$dir"
|
||||
else
|
||||
printDotText "$label" "${fontGreen}save$fontReset"
|
||||
fi
|
||||
done < <(awk 'NF' <<< "$archiveList")
|
||||
|
||||
archiveRemoveCount=$(grep -c . <<< "$archiveRemoveList" || true)
|
||||
if [[ "$archiveRemoveCount" -gt 0 ]]; then
|
||||
printSection "Deleting Directories"
|
||||
while read -r dir; do
|
||||
label="$dir"
|
||||
if ! runError error storageBackupRemove "$dir"; then
|
||||
printDotText "$label" "$labelFail"
|
||||
printDanger "$error"
|
||||
else
|
||||
printDotText "$label" "$labelDone"
|
||||
fi
|
||||
done < <(awk 'NF' <<< "$archiveRemoveList")
|
||||
fi
|
||||
fi
|
||||
printRow
|
||||
}
|
||||
|
||||
# Rotates daily backups on external storage: deletes old entries exceeding $storageDailyKeep, skips today.
|
||||
function cmdStorageBackupDailyDispatch() {
|
||||
local dirList error
|
||||
run dirList error storageFileList "/" d || { printDanger "$error"; return 1; }
|
||||
|
||||
printSection "Config"
|
||||
printDotText "Type" "$storageType"
|
||||
printDotText "Path" "$rsyncPath"
|
||||
printDotText "Daily keep" "$storageDailyKeep"
|
||||
printDotText "Daily pattern" "$backupDailyDirPattern"
|
||||
|
||||
printSection "Directories found"
|
||||
dailyList=$(printf '%s\n' "$dirList" | grep -v "$appDate" | grep -E -- "$backupDailyDirPattern" | sort || true)
|
||||
local dailyCount dailyRemoveCount i=0 num label dailyRemoveList=""
|
||||
dailyCount=$(grep -c . <<< "$dailyList" || true)
|
||||
if [[ "$dailyCount" -gt 0 ]]; then
|
||||
while read -r dir; do
|
||||
((++i))
|
||||
num=$(printf "%0${#dailyCount}d" "$i")
|
||||
label="$num: $fontBlue$dir$fontReset"
|
||||
|
||||
if [[ "$dir" == "$appDate" ]]; then
|
||||
printDotText "$label" "${fontGray}skipped$fontReset"
|
||||
elif (( dailyCount - storageDailyKeep >= i )); then
|
||||
printDotText "$label" "${fontRed}delete$fontReset"
|
||||
dailyRemoveList+=$'\n'"$dir"
|
||||
else
|
||||
printDotText "$label" "${fontGreen}save$fontReset"
|
||||
fi
|
||||
done < <(awk 'NF' <<< "$dailyList")
|
||||
|
||||
dailyRemoveCount=$(grep -c . <<< "$dailyRemoveList" || true)
|
||||
if [[ "$dailyRemoveCount" -gt 0 ]]; then
|
||||
printSection "Deleting Directories"
|
||||
while read -r dir; do
|
||||
label="$dir"
|
||||
if ! runError error storageBackupRemove "$dir"; then
|
||||
printDotText "$label" "$labelFail"
|
||||
printDanger "$error"
|
||||
else
|
||||
printDotText "$label" "$labelDone"
|
||||
fi
|
||||
done < <(awk 'NF' <<< "$dailyRemoveList")
|
||||
fi
|
||||
fi
|
||||
printRow
|
||||
}
|
||||
|
||||
# Synchronizes the local path to external storage (rsync or SSH).
|
||||
# $1 (sourcePath): local path to sync.
|
||||
# [$2] (type): storage type (rsync or ssh); defaults to $storageType.
|
||||
function cmdStoragePathSync() {
|
||||
local sourcePath="$1"
|
||||
[[ -n "$sourcePath" ]] || { printDanger "Source path not specified"; return 1; }
|
||||
|
||||
local type="${2:-$storageType}"
|
||||
local error
|
||||
|
||||
printSection "Config"
|
||||
printDotText "Source" "$sourcePath"
|
||||
if [[ ! -e "$sourcePath" ]]; then
|
||||
printDotText "$sourcePath" "${fontRed}not found$fontReset"
|
||||
return 1
|
||||
fi
|
||||
|
||||
case "$type" in
|
||||
rsync)
|
||||
printDotText "Type" "$type"
|
||||
printDotText "rSync URI" "$rsyncUri"
|
||||
printDotText "rSync path" "$rsyncPath"
|
||||
printSection "Executing"
|
||||
runError error storagePathSyncRsync "$sourcePath" || {
|
||||
printDotText "Process" "$labelFail"
|
||||
printDanger "$error"
|
||||
return 1
|
||||
}
|
||||
;;
|
||||
ssh)
|
||||
printDotText "Type" "$type"
|
||||
printDotText "SSH URI" "$sshUser@$sshHost"
|
||||
printDotText "SSH path" "$sshPath"
|
||||
printSection "Executing"
|
||||
runError error storagePathSyncSSH "$sourcePath" || {
|
||||
printDotText "Process" "$labelFail"
|
||||
printDanger "$error"
|
||||
return 1
|
||||
}
|
||||
;;
|
||||
*)
|
||||
printDotText "Type" "$type $labelUnknown"
|
||||
return 1
|
||||
;;
|
||||
esac
|
||||
|
||||
printDotText "Process" "$labelDone"
|
||||
printRow
|
||||
}
|
||||
|
||||
# Syncs today's daily backup ($backupDailyPath/$appDate) to external storage.
|
||||
function cmdStorageBackupDailySyncLast() {
|
||||
cmdStoragePathSync "$backupDailyPath/$appDate"
|
||||
}
|
||||
|
||||
# Syncs the newest archive backup directory to external storage.
|
||||
function cmdStorageBackupArchiveSyncLast() {
|
||||
local dirList archiveList archiveDir error
|
||||
run dirList error fileList "$backupArchivePath" d || { printDanger "$error"; return 1; }
|
||||
archiveList=$(printf '%s\n' "$dirList" | grep -E -- "$backupArchiveDirPattern" | sort || true)
|
||||
archiveDir=$(tail -n 1 <<< "$archiveList")
|
||||
[[ -n "$archiveDir" ]] || { printDanger "No archive directories found"; return 1; }
|
||||
|
||||
cmdStoragePathSync "$backupArchivePath/$archiveDir"
|
||||
}
|
||||
|
||||
# Interactively selects a local archive backup directory and syncs it to external storage.
|
||||
function cmdStorageBackupArchiveSync() {
|
||||
local dirList error archiveList archiveCount
|
||||
run dirList error fileList "$backupArchivePath" d || { printDanger "$error"; return 1; }
|
||||
archiveList=$(printf '%s\n' "$dirList" | grep -E -- "$backupArchiveDirPattern" | sort || true)
|
||||
archiveCount=$(grep -c . <<< "$archiveList" || true)
|
||||
|
||||
printRow
|
||||
|
||||
local i=0 num dir
|
||||
while read -r dir; do
|
||||
((++i))
|
||||
num=$(printf "%0${#archiveCount}d" "$i")
|
||||
printDotText "$num: $fontBlue$dir$fontReset" "${fontGreen}archive$fontReset"
|
||||
done < <(awk 'NF' <<< "$archiveList")
|
||||
|
||||
printRow
|
||||
|
||||
local input item selected
|
||||
read -r -p "Specify the backup number: " input
|
||||
printRow
|
||||
|
||||
[[ -z "$input" ]] && input=0
|
||||
[[ "$input" =~ ^[0-9]+$ ]] || { printDanger "Invalid backup number"; return 1; }
|
||||
item=$((10#$input))
|
||||
selected=$(awk 'NF {n++} n == item {print; exit}' item="$item" <<< "$archiveList")
|
||||
[[ -n "$selected" ]] || { printDanger "Unknown backup number"; return 1; }
|
||||
|
||||
cmdStoragePathSync "$backupArchivePath/$selected"
|
||||
}
|
||||
|
||||
# Interactively selects a local daily backup directory and syncs it to external storage.
|
||||
function cmdStorageBackupDailySync() {
|
||||
local dirList error dailyList dailyCount
|
||||
run dirList error fileList "$backupDailyPath" d || { printDanger "$error"; return 1; }
|
||||
dailyList=$(printf '%s\n' "$dirList" | grep -E -- "$backupDailyDirPattern" | sort || true)
|
||||
dailyCount=$(grep -c . <<< "$dailyList" || true)
|
||||
|
||||
printRow
|
||||
|
||||
local i=0 num dir
|
||||
while read -r dir; do
|
||||
((++i))
|
||||
num=$(printf "%0${#dailyCount}d" "$i")
|
||||
printDotText "$num: $fontBlue$dir$fontReset" "${fontGreen}daily$fontReset"
|
||||
done < <(awk 'NF' <<< "$dailyList")
|
||||
|
||||
printRow
|
||||
|
||||
local input item selected
|
||||
read -r -p "Specify the backup number: " input
|
||||
printRow
|
||||
|
||||
[[ -z "$input" ]] && input=0
|
||||
[[ "$input" =~ ^[0-9]+$ ]] || { printDanger "Invalid backup number"; return 1; }
|
||||
item=$((10#$input))
|
||||
selected=$(awk 'NF {n++} n == item {print; exit}' item="$item" <<< "$dailyList")
|
||||
[[ -n "$selected" ]] || { printDanger "Unknown backup number"; return 1; }
|
||||
|
||||
cmdStoragePathSync "$backupDailyPath/$selected"
|
||||
}
|
||||
|
||||
# Dispatches interactive backup sync by type.
|
||||
# $1 (type): backup type: archive or daily.
|
||||
function cmdStorageBackupSync() {
|
||||
local type
|
||||
type="$1"
|
||||
|
||||
case "$type" in
|
||||
archive)
|
||||
cmdStorageBackupArchiveSync
|
||||
;;
|
||||
daily)
|
||||
cmdStorageBackupDailySync
|
||||
;;
|
||||
*)
|
||||
printDanger "Unknown type backup: $type";
|
||||
return 1
|
||||
;;
|
||||
esac
|
||||
}
|
||||
|
||||
# Interactively selects a backup directory on external storage and removes it.
|
||||
function cmdStorageBackupRemove() {
|
||||
local dirList error dirCount archiveList dailyList dir i=0 num label
|
||||
run dirList error storageFileList "/" d || { printDanger "$error"; return 1; }
|
||||
|
||||
dirCount=$(grep -c . <<< "$dirList" || true)
|
||||
archiveList=$(printf '%s\n' "$dirList" | grep -E -- "$backupArchiveDirPattern" | sort || true)
|
||||
dailyList=$(printf '%s\n' "$dirList" | grep -E -- "$backupDailyDirPattern" | sort || true)
|
||||
|
||||
printRow
|
||||
|
||||
while read -r dir; do
|
||||
((++i))
|
||||
num=$(printf "%0${#dirCount}d" "$i")
|
||||
label="$num: $fontBlue$dir$fontReset"
|
||||
|
||||
if listContains "$dir" "$archiveList"; then
|
||||
printDotText "$label" "${fontGreen}archive$fontReset"
|
||||
elif listContains "$dir" "$dailyList"; then
|
||||
printDotText "$label" "${fontGreen}daily$fontReset"
|
||||
else
|
||||
printDotText "$label" "$labelUnknown"
|
||||
fi
|
||||
done < <(awk 'NF' <<< "$dirList")
|
||||
|
||||
printRow
|
||||
|
||||
local input item selected
|
||||
read -r -p "Specify the backup number: " input
|
||||
printRow
|
||||
|
||||
[[ -z "$input" ]] && input=0
|
||||
[[ "$input" =~ ^[0-9]+$ ]] || { printDanger "Invalid backup number"; return 1; }
|
||||
item=$((10#$input))
|
||||
selected=$(awk 'NF {n++} n == item {print; exit}' item="$item" <<< "$dirList")
|
||||
[[ -n "$selected" ]] || { printDanger "Unknown backup number"; return 1; }
|
||||
|
||||
if ! runError error storageBackupRemove "$selected"; then
|
||||
printDotText "$selected" "$labelFail"
|
||||
printDanger "$error"
|
||||
printRow
|
||||
return 1
|
||||
fi
|
||||
printDotText "$selected" "$labelDone"
|
||||
|
||||
printRow
|
||||
}
|
||||
|
||||
# Compares local and remote backup directories, showing which exist on each side.
|
||||
function cmdStorageBackupCompare() {
|
||||
local dirList error localArchiveList localDailyList remoteArchiveList remoteDailyList
|
||||
|
||||
run dirList error fileList "$backupArchivePath" d || { printDanger "Archive path: $error"; return 1; }
|
||||
localArchiveList=$(printf '%s\n' "$dirList" | grep -E -- "$backupArchiveDirPattern" | sort || true)
|
||||
|
||||
run dirList error fileList "$backupDailyPath" d || { printDanger "Archive path: $error"; return 1; }
|
||||
localDailyList=$(printf '%s\n' "$dirList" | grep -E -- "$backupDailyDirPattern" | sort || true)
|
||||
|
||||
run dirList error storageFileList "/" d || { printDanger "$error"; return 1; }
|
||||
remoteArchiveList=$(printf '%s\n' "$dirList" | grep -E -- "$backupArchiveDirPattern" | sort || true)
|
||||
remoteDailyList=$(printf '%s\n' "$dirList" | grep -E -- "$backupDailyDirPattern" | sort || true)
|
||||
|
||||
printSection "Local"
|
||||
printDotText "Archive" "$(grep -c . <<< "$localArchiveList" || true)"
|
||||
printDotText "Daily" "$(grep -c . <<< "$localDailyList" || true)"
|
||||
|
||||
printSection "Remote"
|
||||
printDotText "Archive" "$(grep -c . <<< "$remoteArchiveList" || true)"
|
||||
printDotText "Daily" "$(grep -c . <<< "$remoteDailyList" || true)"
|
||||
|
||||
local allDirs
|
||||
allDirs=$(printf '%s\n' "$localArchiveList" "$localDailyList" "$remoteArchiveList" "$remoteDailyList" | awk 'NF' | sort -u)
|
||||
|
||||
printSection "Comparison"
|
||||
local dir localStatus remoteStatus
|
||||
out="${fontRed}X$fontReset"
|
||||
localIn="${fontGreen}L$fontReset"
|
||||
remoteIn="${fontGreen}R$fontReset"
|
||||
while read -r dir; do
|
||||
localStatus="$out"
|
||||
remoteStatus="$out"
|
||||
|
||||
if listContains "$dir" "$localArchiveList"; then
|
||||
localStatus="$localIn"
|
||||
elif listContains "$dir" "$localDailyList"; then
|
||||
localStatus="$localIn"
|
||||
fi
|
||||
if listContains "$dir" "$remoteArchiveList"; then
|
||||
remoteStatus="$remoteIn"
|
||||
elif listContains "$dir" "$remoteDailyList"; then
|
||||
remoteStatus="$remoteIn"
|
||||
fi
|
||||
|
||||
printDotText "$fontBlue$dir$fontReset" "[ $localStatus : $remoteStatus ]"
|
||||
done < <(awk 'NF' <<< "$allDirs")
|
||||
|
||||
printRow
|
||||
}
|
||||
Reference in New Issue
Block a user