从 shell 脚本执行命令失败

execute command from shell script fails

当我 运行 我的脚本失败时:

# sh -x ./rsync.sh 
...
+ rsync --safe-links --password-file=/etc/rsync.secret -rtvun --include='*.log*.gz' --filter='-! */' --prune-empty-dirs /some/path foo@hostname::foo
Unknown filter rule: `'-!'
rsync error: syntax or usage error (code 1) at exclude.c(904) [client=3.1.1]

但是当我复制并粘贴 rsync --safe-links .... 行并执行它时它工作正常。

rsync.sh:

#!/bin/bash

rsync_opts="--safe-links --password-file=/etc/rsync.secret -rtvu"

while read path hostname volume extra_opts; do
  rsync ${rsync_opts} ${extra_opts} ${path} ${volume}@${hostname}::${volume}
done < /etc/rsync.paths

rsync.paths:

/some/path/ hostname foo --include='*.log*.gz' --filter='-! */' --prune-empty-dirs

有谁知道为什么脚本会失败,而当我手动 运行 命令时却能正常工作?我该如何解决?

更新: 当我使用 eval "rsync ..." 时它工作正常,但我仍然不知道为什么没有它就不能工作:/

您的问题是您的脚本将文本 --filter='-! */' --prune-empty-dirs 读取到变量 $extra_opts 中,该变量按字面意思传递给命令,包括撇号。所以它被分成以下参数:--filter='-!*/'--prune-empty-dirs。但是,当你 eval 它时,整行都会传递给 shell 解释器,它会按照你想要的方式解释撇号,这就是它起作用的原因。

此外,由于您的脚本使用 bash,因此您应该使用 bash -x 而不是 sh -x 来调试它。