Currently I have this backup script working just fine in Unraid. I can add as many backup jobs to the array below as I like and the script will loop through these one after the other until all are done.
#!/bin/bash
# backup source to destination
backup_jobs=(
# source # destination
"/mnt/user/isos" "/mnt/disks/Backup"
"/mnt/user/data" "/mnt/disks/Backup"
)
# loop through all backup jobs
for i in "${!backup_jobs[@]}"; do
# get source path and skip to next element
! (( i % 2 )) && src_path="${backup_jobs[i]}" && continue
# get destination path
dst_path="${backup_jobs[i]}"
#run backup
rsync -av --delete --log-file=/mnt/disks/Backup/rsync-logs/log.`date ' %Y_%m_%d__%H_%M_%S'`.log --progress --exclude '.Recycle.Bin' "$src_path" "$dst_path"
Now I would like to also have a subfolder for the rsync-logs per backup job.
For that I'd like to add a name to the array for each job - but I cannot figure out how to get the loop to load that 3rd variable per line per loop like the other 2 variables. :(
backup_jobs=(
# source # destination # jobname
"/mnt/user/isos" "/mnt/disks/Backup" "isos"
"/mnt/user/data" "/mnt/disks/Backup" "backup"
)
Anyone able to help? :)
CodePudding user response:
Use i % 3
instead of i % 2
. This will be 0
for the source path, 1
for the destination path, and 2
for the job name.
for i in "${!backup_jobs[@]}"; do
case $(($i % 3)) in
0) src_path="${backup_jobs[i]}"; continue ;;
1) dst_path="${backup_jobs[i]}"; continue ;;
2) job_name="${backup_jobs[i]}" ;;
esac
#run backup
rsync -av --delete --log-file=/mnt/disks/Backup/rsync-logs/"$job_name"/log.`date ' %Y_%m_%d__%H_%M_%S'`.log --progress --exclude '.Recycle.Bin' "$src_path" "$dst_path"
done
CodePudding user response:
#!/bin/bash
declare -A backup_jobs=(
[source,1]="/mnt/user/isos"
[destination,1]="/mnt/disks/Backup"
[jobname,1]="isos"
[foo,1]="foo"
[bar,1]="bar"
[source,2]="/mnt/user/data"
[destination,2]="/mnt/disks/Backup"
[jobname,2]="backup"
[foo,2]="foo"
[bar,2]="bar"
)
LEN=$(tr ' ' '\n' <<<"${!backup_jobs[@]}"|sort -r|sed -n 's/.*,//; 1p')
for((i=1; i<=LEN; i )); do
echo "------- Backup $i -------"
echo "source: ${backup_jobs[source,$i]}"
echo "destination: ${backup_jobs[destination,$i]}"
echo "jobname: ${backup_jobs[jobname,$i]}"
# rsync -av --delete --log-file=/mnt/disks/Backup/rsync-logs/${backup_jobs[jobname,$i]}/log.`date ' %Y_%m_%d__%H_%M_%S'`.log --progress --exclude '.Recycle.Bin' "${backup_jobs[source,$i]}" "${backup_jobs[destination,$i]}"
done
Output:
------- Backup 1 -------
source: /mnt/user/isos
destination: /mnt/disks/Backup
jobname: isos
------- Backup 2 -------
source: /mnt/user/data
destination: /mnt/disks/Backup
jobname: backup
CodePudding user response:
Using a function which benefit of built-in arguments stack features is certainly a more appropriate and direct approach; rather than re-implementing the arguments stack using shell arithmetic on array indexes.
With bash array:
#!/bin/bash
backup_jobs=(
# source # destination # jobname
"/mnt/user/isos" "/mnt/disks/Backup" "isos"
"/mnt/user/data" "/mnt/disks/Backup" "backup"
)
do_backup() {
while
src_path=$1
dst_path=$2
job_name=$3
shift 3 2> /dev/null
do #run backup
echo rsync \
--archive --verbose --delete \
--log-file="/mnt/disks/Backup/rsync-logs/$job_name/log.$(date ' %Y_%m_%d__%H_%M_%S').log" \
--progress --exclude '.Recycle.Bin' \
"$src_path" "$dst_path"
done
}
do_backup "${backup_jobs[@]}"
Now even an array is not necessary, and it can stick to the POSIX-shell grammar:
#!/bin/sh
do_backup() {
while
src_path=$1
dst_path=$2
job_name=$3
shift 3 2> /dev/null
do #run backup
echo rsync \
--archive --verbose --delete \
--log-file="/mnt/disks/Backup/rsync-logs/$job_name/log.$(date ' %Y_%m_%d__%H_%M_%S').log" \
--progress --exclude '.Recycle.Bin' \
"$src_path" "$dst_path"
done
}
# source # destination # jobname
do_backup \
"/mnt/user/isos" "/mnt/disks/Backup" "isos" \
"/mnt/user/data" "/mnt/disks/Backup" "backup"