188 lines
4.8 KiB
Bash
Executable File
188 lines
4.8 KiB
Bash
Executable File
#!/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} <json_config_file>"
|
|
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}"
|
|
|