bash脚本中的命令无法使用变量参数

时间:2015-05-24 02:06:05

标签: linux bash

我试图围绕 bazaarvcb 实用程序构建一个bash脚本,但在构造参数时我遇到了一些问题。 基本上,这是我想要执行的命令(简化版):

bazaarvcb backup -H 192.168.1.100 -u user -p password --roll-out 4 \
--exclude-disk "[Datastore1] MyVM - NAS/MyVM-NAS_1.vmdk" \
--exclude-disk "[Datastore2] MyVM - NAS/MyVM-NAS_2.vmdk" \
"MyVM - NAS" "/home/user/backup/MyVM - NAS/"

在命令行上执行上述操作或在简单的bash脚本中粘贴它,一切都很好。但是当我尝试将排除磁盘(甚至VM名称)替换为脚本中的变量参数时,我遇到了问题。

示例:

#!/usr/bin/env bash

set -o xtrace

readonly __VM="MyVM - NAS"
readonly __BACKUPROOT="/home/user/backup/MyVM - NAS/"

readonly -a __EXCLUDE_DISKS=( \
'[Datastore1] MyVM - NAS/MyVM-NAS_1.vmdk' \
'[Datastore2] MyVM - NAS/MyVM-NAS_2.vmdk' )

disks_excluded=""
for (( i = 0 ; i < ${#__EXCLUDE_DISKS[@]} ; i++ )); do
    disks_excluded+="--exclude-disk \"${__EXCLUDE_DISKS[$i]}\" "
done

bazaarvcb backup -H 192.168.1.100 -u user -p password --roll-out 4 ${disks_excluded} "${__VM}" "${__BACKUPROOT}"

执行上述脚本时的结果是:

+ readonly '__VM=MyVM - NAS'
+ __VM='MyVM - NAS'
+ readonly '__BACKUPROOT=/home/user/backup/MyVM - NAS/'
+ __BACKUPROOT='/home/user/backup/MyVM - NAS/'
+ __EXCLUDE_DISKS=('[Datastore1] MyVM - NAS/MyVM-NAS_1.vmdk' '[Datastore2] MyVM - NAS/MyVM-NAS_2.vmdk')
+ readonly -a __EXCLUDE_DISKS
+ disks_excluded=
+ (( i = 0  ))
+ (( i < 2  ))
+ disks_excluded+='--exclude-disk "[Datastore1] MyVM - NAS/MyVM-NAS_1.vmdk" '
+ (( i++  ))
+ (( i < 2  ))
+ disks_excluded+='--exclude-disk "[Datastore2] MyVM - NAS/MyVM-NAS_2.vmdk" '
+ (( i++  ))
+ (( i < 2  ))
+ bazaarvcb backup -H 192.168.1.100 -u user -p password --roll-out 4 --exclude-disk '"[Datastore1]' MyVM - 'NAS/MyVM-NAS_1.vmdk"' --exclude-disk '"[Datastore2]' MyVM - 'NAS/MyVM-NAS_2.vmdk"' 'MyVM - NAS' '/home/user/backup/MyVM - NAS/'
usage: bazaarvcb [-h] [--version]  ...
bazaarvcb: error: unrecognized arguments: NAS/MyVM-NAS_1.vmdk" MyVM - NAS/MyVM-NAS_2.vmdk" MyVM - NAS /home/user/backup/MyVM - NAS/

任何帮助都将不胜感激。

1 个答案:

答案 0 :(得分:1)

shell在扩展变量引用之前解析引号,因此将引号放在变量的值中并没有做任何有用的事情 - 当它们被扩展到命令时,它会被&#39;他们太迟了没有达到预期的效果。因此,当您使用:

...
disks_excluded+="--exclude-disk \"${__EXCLUDE_DISKS[$i]}\" "
...
bazaarvcb ... ${disks_excluded} ...

bazaarvcb会传递参数,例如&#39; - exclude-disk&#39;,&#39;&#34; [Datastore1]&#34;,&#39; MyVM&#39;, &#39; - &#39;和&#39; NAS / MyVM-NAS_1.vmdk&#34;&#39;。双引号被视为参数的一部分,而不是参数的引用!幸运的是,解决方案很简单:将disks_excluded存储为数组,就像使用__EXCLUDE_DISKS一样。请注意,您还可以通过迭代数组元素而不是索引来简化for循环:

...
disks_excluded=() # Note that this declares disks_excluded as an empty array
for disk in "${__EXCLUDE_DISKS[@]}"; do
    disks_excluded+=("--exclude-disk" "${disk}")
done

bazaarvcb backup -H 192.168.1.100 -u user -p password --roll-out 4 "${disks_excluded[@]}" "${__VM}" "${__BACKUPROOT}"

请注意,${__EXCLUDE_DISKS[@]}${disks_excluded[@]}周围的双引号是必需的(与[@] s一样)。