juliushibert
juliushibert

Reputation: 414

Passing variables from external bash file not behaving as expected

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

Answers (1)

chepner
chepner

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

Related Questions