从外部bash文件传递变量的行为不符合预期

时间:2016-01-26 09:33:28

标签: bash variables backup rsync

我有一个bash脚本,它使用rsync将一些文件从我的本地桌面备份到局域网上的远程机器。

我的主脚本在一个单独的.sh文件中包含一些可自定义的变量,以便于维护,部署和git管理。

所以我有这个目录结构

sync-backup-to-cp.sh
config/settings.sh

以下代码将config / settings.sh包含在主sync-backup-to-cp.sh

#! /bin/bash

#load variables file
source /Users/enwhat/Dropbox/Flex/Scripts/mac/rysnc-backup-to-cp/config/settings.sh

但是导入的变量的行为不符合预期。如果我在任何变量中有任何空格,则会抛出有关变量无效的错误。似乎bash正在奇怪地解释这一点。

IE中。 rsync_opts =“ - verbose --archive”将导致脚本中断并运行错误,例如“提供无效数字参数或未知参数”。其中rsync_opts =“ - verbose”运行完美。

为了帮助说明脚本,我已经采用了一些代码片段,显示了到目前为止的流程

from:config / settings.sh

RSYNC_OPTS=( --bwlimit=1000 --verbose ) 

从我的主脚本中,有一个函数调用,传入这些变量。

backup "$RSYNC_BIN" "$BACKUP_FILE_LIST" "$EXCLUDE_FILE_LIST" "$SSH_PORT" "$SSH_KEY" "$SOURCE" "$DESTINATION" "$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}"

}

1 个答案:

答案 0 :(得分:2)

由于您引用$rsync_opts,因此整个值将作为包含空格的单个参数传递给rsync。为了使每个选项作为单独的参数传递,您需要保持参数展开不加引号:

rsync $rsync_opts

但是,你不能包含实际包含这样的空格的参数;所有空格都被shell视为分隔参数。存储参数的正确方法是使用数组:

rsync_opts=( --verbose --archive )
rsync "${rsync_opts[@]}"

对于您当前的使用案例可能没有必要,但最好养成以正确的方式做事的习惯,以避免以后出现令人讨厌的意外。

例如,

local -a l_rsync_opts
l_rsync_opts=(--bwlimit=1000 --verbose --rsync-path="sudo rsync")

更新:根据您的修改,您需要执行以下操作:

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}"

}
相关问题