From d371bb90566ecfb1799f7ef3136733cfe6235a04 Mon Sep 17 00:00:00 2001 From: Oleg Sheynin Date: Wed, 11 Jun 2025 09:17:58 -0400 Subject: [PATCH] . --- backup/backup_by_json.sh | 188 ++++++++++++++++++++++++++++++++++++++- 1 file changed, 187 insertions(+), 1 deletion(-) mode change 120000 => 100755 backup/backup_by_json.sh diff --git a/backup/backup_by_json.sh b/backup/backup_by_json.sh deleted file mode 120000 index c430686..0000000 --- a/backup/backup_by_json.sh +++ /dev/null @@ -1 +0,0 @@ -/works/repos/admin/storage_backup.sh \ No newline at end of file diff --git a/backup/backup_by_json.sh b/backup/backup_by_json.sh new file mode 100755 index 0000000..1338ecd --- /dev/null +++ b/backup/backup_by_json.sh @@ -0,0 +1,187 @@ +#!/bin/bash +# Script to create and run rsync command based on JSON configuration + +: <<'COMMENT' +Config File Example (local backup for hs01 +========================================== +{ + "Name" : "hs01", + "Host" : "", + + "BackupHost" : "", + "BackupRootDir" : "/backup/hs01", + + "Filesystems" : ["/etc", "/opt", "/archive", "/data", "/works" ], + + "RsyncOptions" : ["-arxv", "--delete", "--relative" ], + + "Exclude" : ["*var/tmp*" + , "*var/lib/ntp/proc*" + , "*.cache*" + , "*root/.mozilla*" + , "*var/cache*" + , "*var/spool*" + , "*/.kde4/*" + , "/tmp" + ], + + "DailySnapshots" : false, + "PruneBackupDays" : 1 + +} +COMMENT + + +usage() { + echo "Usage: ${Script} " + exit 1 +} + + +# Check if jq is installed +if ! command -v jq &>/dev/null; then + echo "Error: jq is required for JSON processing. Install it and try again." + exit 1 +fi + +# Verify configuration +verify_config() { + local config_file="$1" + + # Check if required directories and files exist + local backup_root_dir + backup_root_dir=$(jq -r '.BackupRootDir' "$config_file") + if [[ ! -d "$backup_root_dir" ]]; then + echo "----- Error: BackupRootDir ($backup_root_dir) does not exist." + mkdir -p "${backup_root_dir}" + fi + +} + +# Run rsync +run_rsync() { + local cmdlist=("$@") + echo "----- Running rsync: ${cmdlist[*]}" + "${cmdlist[@]}" +} + +# Prune old backups +prune_backup_dirs() { + local bkp_host="$1" + local root_dir="$2" + local days="$3" + + echo "----- Looking for files to prune..." + local cmd="cd $root_dir && ls -rd 2* | awk -v days=$days '{ if (NR > days) print }'" + [[ -n "$bkp_host" ]] && cmd="ssh $bkp_host \"$cmd\"" + + echo "----- Command: $cmd" + local files + files=$(eval "$cmd") + if [[ -n "$files" ]]; then + echo "----- Found files to prune:" + echo "$files" + local prune_cmd="rm -rf $(echo "$files" | xargs -I {} echo "$root_dir/{}")" + [[ -n "$bkp_host" ]] && prune_cmd="ssh $bkp_host \"$prune_cmd\"" + echo "----- Executing: $prune_cmd" + eval "$prune_cmd" + else + echo "----- Nothing to prune." + fi +} + +# Generate rsync arguments +get_rsync_arguments() { + local config_file="$1" + local dt="$2" + local fs="$3" + + local bkp_root_dir + bkp_root_dir=$(jq -r '.BackupRootDir' "$config_file") + local daily_snapshots + daily_snapshots=$(jq -r '.DailySnapshots' "$config_file") + local rsync_options + rsync_options=$(jq -r '.RsyncOptions[]' "$config_file") + local exclude_list + exclude_list=$(jq -r '.Exclude[]' "$config_file") + + local bkp_dir="$bkp_root_dir" + [[ "$daily_snapshots" == "true" ]] && bkp_dir="$bkp_root_dir/$dt" + + local cmdlist=("rsync" $rsync_options) + for excl in $exclude_list; do + cmdlist+=("--exclude=$excl") + done + [[ "$daily_snapshots" == "true" ]] && cmdlist+=("--link-dest=$bkp_root_dir/current") + + local src_host + src_host=$(jq -r '.Host' "$config_file") + [[ -n "$src_host" ]] && src_host="$src_host:" + + local tgt_host + tgt_host=$(jq -r '.BackupHost' "$config_file") + [[ -n "$tgt_host" ]] && tgt_host="$tgt_host:" + + cmdlist+=("${src_host}${fs}" "${tgt_host}${bkp_dir}/") + + echo "${cmdlist[@]}" +} + +# Main function +main() { + local config_file="$1" + if [[ ! -f "$config_file" ]]; then + echo "----- Error: Configuration file $config_file does not exist." + exit 1 + fi + + if ! verify_config "$config_file"; then + exit 1 + fi + + local dt + dt=$(date +%Y%m%d) + + local filesystems + filesystems=$(jq -r '.Filesystems[]' "$config_file") + for fs in $filesystems; do + echo "----- Processing filesystem: $fs" + local cmdlist + cmdlist=($(get_rsync_arguments "$config_file" "$dt" "$fs")) + run_rsync "${cmdlist[@]}" + done + + local daily_snapshots + daily_snapshots=$(jq -r '.DailySnapshots' "$config_file") + if [[ "$daily_snapshots" == "true" ]]; then + local bkp_root_dir + bkp_root_dir=$(jq -r '.BackupRootDir' "$config_file") + local bkp_host + bkp_host=$(jq -r '.BackupHost' "$config_file") + local cmd="ln -snf $bkp_root_dir/$dt $bkp_root_dir/current" + [[ -n "$bkp_host" ]] && cmd="ssh $bkp_host \"$cmd\"" + echo "----- Switching current symlink: $cmd" + eval "$cmd" + + local prune_days + prune_days=$(jq -r '.PruneBackupDays' "$config_file") + if [[ "$prune_days" -gt 0 ]]; then + local bkp_root_dir + bkp_root_dir=$(jq -r '.BackupRootDir' "$config_file") + local bkp_host + bkp_host=$(jq -r '.BackupHost' "$config_file") + prune_backup_dirs "$bkp_host" "$bkp_root_dir" "$prune_days" + fi + fi +} + +# Entry point +Script=${0} +Config=${1} +if [[ $# -lt 1 ]]; then + usage + exit 1 +fi + +main "${Config}" +