确实很难让命令参数变量与 rsync 配合使用。我看到的行为是来自脚本的此错误:
rsync: connection unexpectedly closed (0 bytes received so far) [sender]
rsync error: unexplained error (code 255) at io.c(601) [sender=3.0.7]
但是脚本通过 echo 输出要运行的命令,并且将完全相同的命令复制粘贴到终端(或回到脚本中作为第一行,后面跟着退出)可以正常工作?!
执行此 rsync 的脚本代码(在这种情况下 check_flags 为空):
rsync_cmd=(${check_flags} -rWltpgoDvdHP --delete-before -- \"${backup_dir}\" \"admin@nas-1:${backup_basename}/\")
echo "CMD to run: rsync ${rsync_cmd[@]}"
rsync ${rsync_cmd[@]}
输出:
CMD to run: rsync -rWltpgoDvdHP --delete-before -- "/share/CACHEDEV1_DATA/veeam_backup_daily/Daily backup _@1am__1" "admin@nas-1:/share/CACHEDEV1_DATA/veeam_backup_daily/"
我在网上看到使用数组应该可以解决这个问题,但在本例中却没有。我确信这是一个简单的解决方法,但它让我抓狂!
答案1
shell 在替换变量之前会解析引号,因此在变量值中包含引号并不会达到预期的效果(并且echo
非常具有误导性,因为它没有显示这种区别)。您应该做的是在定义数组时使用未转义的引号(这样它们将被解析为数组元素周围的分隔符,而不是数组值的一部分),然后用双引号括住对数组的引用(这样它就不会对数组中的值进行单词拆分或通配符扩展)。我还将用 替换该echo
命令,printf
这将更准确地显示将要发生的事情:
rsync_cmd=(${check_flags} -rWltpgoDvdHP --delete-before -- "${backup_dir}" "admin@nas-1:${backup_basename}/")
printf "%q " CMD to run: rsync "${rsync_cmd[@]}"
printf "\n"
rsync "${rsync_cmd[@]}"
请注意,可能printf
不会显示您期望的内容——它将打印一个相等的将要执行的命令的表示,但每个参数都有许多不同的等效表示,它会根据其偏好选择一个,而不是最初输入的方式。顺便说一句,您也可以使用它set -x
来调试类似的东西,但(与 一样printf "%q "
)它可能使用与您预期不同的表示。