Reputation: 414
I have a bash script that’s using rsync to backup some files from my local desktop to a remote machine on my LAN.
I have the main script with some customisable variables in a separate .sh file to make for easy maintenance, deployment and git management.
So I have this dir structure
sync-backup-to-cp.sh
config/settings.sh
And the following code to include the config/settings.sh into the main sync-backup-to-cp.sh
#! /bin/bash
#load variables file
source /Users/enwhat/Dropbox/Flex/Scripts/mac/rysnc-backup-to-cp/config/settings.sh
However the imported variables aren’t behaving as expected. If I have any space in any of the variables it throws an error about the variables being invalid. It seems that bash is interpreting this oddly.
Ie. rsync_opts="--verbose --archive” will cause the script to break and run an error such as “invalid numeric arguments or unknown arguments supplied”. Where as rsync_opts="--verbose” runs perfectly.
To help illustrate the script I've taken some snippets of the code showing the flow with help so far
from: config / settings.sh
RSYNC_OPTS=( --bwlimit=1000 --verbose )
from my main script, there's a function call where these variables are passed in.
backup "$RSYNC_BIN" "$BACKUP_FILE_LIST" "$EXCLUDE_FILE_LIST" "$SSH_PORT" "$SSH_KEY" "$SOURCE" "$DESTINATION" "$RSYNC_OPTS[*]"
then the full function
function backup(){ #uses rsync to backup to server
#takes 8 args 1
#define local vars
local l_rsync_bin=$1
local l_rsync_backup_file_list=$2
local l_rsync_exclude_file_list=$3
local l_rsync_ssh_port=$4
local l_rsync_ssh_key=$5
local l_rsync_source=$6
local l_rsync_dest=$7
local l_rsync_opts=$8
#local l_time
#l_time=$(date)
#caffinate stops system from sleeping
echo ""$l_rsync_bin" "$l_rsync_opts" --verbose --archive --recursive --numeric-ids --human-readable --partial --progress --relative --itemize-changes --stats --rsync-path="sudo rsync" --delete-during --files-from="${l_rsync_backup_file_list}" --exclude-from="${l_rsync_exclude_file_list}" -e "ssh -q -p ${l_rsync_ssh_port} -i ${l_rsync_ssh_key}" "${l_rsync_source}" "${l_rsync_dest}""
caffeinate -s "$l_rsync_bin" "$l_rsync_opts" --verbose --archive --recursive --numeric-ids --human-readable --partial --progress --relative --itemize-changes --stats --rsync-path="sudo rsync" --delete-during --files-from="${l_rsync_backup_file_list}" --exclude-from="${l_rsync_exclude_file_list}" -e "ssh -q -p ${l_rsync_ssh_port} -i ${l_rsync_ssh_key}" "${l_rsync_source}" "${l_rsync_dest}"
}
Upvotes: 1
Views: 405
Reputation: 532333
Since you are quoting $rsync_opts
, the entire value is passed as a single, whitespace-containing argument to rsync
. In order for each option to be passed as a separate argument, you need to leave the parameter expansion unquoted:
rsync $rsync_opts
However, you can't include arguments that actually contain whitespace like this; all whitespace is treated by the shell as separating arguments. The right way to store arguments is to use an array:
rsync_opts=( --verbose --archive )
rsync "${rsync_opts[@]}"
It may not be necessary for your current use case, but it's a good idea to get into the habit of doing things the right way to avoid nasty surprises later.
For example,
local -a l_rsync_opts
l_rsync_opts=(--bwlimit=1000 --verbose --rsync-path="sudo rsync")
UPDATE: Based on your edit, you need to do the following:
backup ... "${RSYNC_OPTS[@]}" # @, not *
# Note the changes involving l_rsync_opts
function backup(){ #uses rsync to backup to server
#takes 8 args 1
#define local vars
local l_rsync_bin=$1
local l_rsync_backup_file_list=$2
local l_rsync_exclude_file_list=$3
local l_rsync_ssh_port=$4
local l_rsync_ssh_key=$5
local l_rsync_source=$6
local l_rsync_dest=$7
local l_rsync_opts=( "${@:8}" )
#local l_time
#l_time=$(date)
#caffinate stops system from sleeping
echo ""$l_rsync_bin" "${l_rsync_opts[@]}" --verbose --archive --recursive --numeric-ids --human-readable --partial --progress --relative --itemize-changes --stats --rsync-path="sudo rsync" --delete-during --files-from="${l_rsync_backup_file_list}" --exclude-from="${l_rsync_exclude_file_list}" -e "ssh -q -p ${l_rsync_ssh_port} -i ${l_rsync_ssh_key}" "${l_rsync_source}" "${l_rsync_dest}""
caffeinate -s "$l_rsync_bin" "${l_rsync_opts[@]}" --verbose --archive --recursive --numeric-ids --human-readable --partial --progress --relative --itemize-changes --stats --rsync-path="sudo rsync" --delete-during --files-from="${l_rsync_backup_file_list}" --exclude-from="${l_rsync_exclude_file_list}" -e "ssh -q -p ${l_rsync_ssh_port} -i ${l_rsync_ssh_key}" "${l_rsync_source}" "${l_rsync_dest}"
}
Upvotes: 2