【问题标题】:Command inside bash script not executing correctly with variable parameters [duplicate]bash脚本中的命令无法使用可变参数正确执行[重复]
【发布时间】:2015-05-24 13:49:21
【问题描述】:

我正在尝试围绕 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 脚本中,一切正常。但是当我尝试将排除磁盘(甚至虚拟机名称)替换为脚本中的变量参数时,我遇到了问题。

例子:

#!/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/

任何帮助将不胜感激。

【问题讨论】:

  • 确保参数中没有空格
  • 是的,这是我的第一个方法。事实上,我可以将我的 VM 名称从 "MyVM - NAS" 更改为 "MyVM-NAS",但由于引用 VMDK 磁盘时的语法 ([Datastore] folder/disk.vmdk),--exclude-disk 参数的问题仍然存在。

标签: linux bash


【解决方案1】:

shell 在扩展变量引用之前解析引号,因此将引号放在变量的值中并没有任何用处——当它们被扩展到命令中时,它们已经太晚了,无法达到预期的效果。因此,当您使用时:

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

bazaarvcb 获取传递的参数,例如 '--exclude-disk'、'"[Datastore1]"、'MyVM'、'-' 和 'NAS/MyVM-NAS_1.vmdk"'。双引号是被视为参数的一部分,而不是参数的引号!幸运的是,解决方案很简单:将 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 也是如此)。

【讨论】:

  • 是的,它就像你提到的那样工作。谢谢!
猜你喜欢
  • 2014-06-28
  • 2011-10-16
  • 1970-01-01
  • 2021-11-25
  • 2013-10-18
  • 2017-10-07
  • 2018-05-15
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多