在Bash rsync脚本中出错

一个bash脚本有以下行

rsync $OPTS $BACKDIR $USER@$DEST:$DESTDIR 

但其中一个选项是rsh='ssh -p2222'它抱怨说:

  rsync: -p2222': unknown option rsync error: syntax or usage error (code 1) at main.c(1425) [client=3.0.7] 

但是当我将脚本更改为:

  echo rsync $OPTS $BACKDIR $USER@$DEST:$DESTDIR 

并手动运行打印的命令它的工作。

请指教

简短的回答:见BashFAQ#50 。

长的回答:把命令(或命令的一部分)变成variables,然后把它们恢复完整是很复杂的。 当shell在命令行上展开一个variables时,如果variables是双引号,那么它就不会被parsing(参见@Dennis Williamson的答案); 如果它不在引号中,则它中的空格会被parsing为参数中断,但引号和转义不会被parsing(这就是为什么在rsync之一的参数中有一个字面引号的错误)。 在任何一种情况下,将引号放在variables的值中都没有用处。

但是,有几种方法可以修复脚本,具体取决于OPTS的复杂程度:

  1. 如果-rsh是OPTS中唯一的东西,那就用双引号(如Dennis Williamson的回答):

     OPTS='--rsh=ssh -p2222' rsync "$OPTS" "$BACKDIR" "$USER@$DEST:$DESTDIR" 

    (注意其他参数周围的双引号:这是为了防止错误分析,如果它们包含空格,并且通常是良好的脚本卫生。)

  2. 如果OPTS的内容是恒定的(或至less是-rsh部分),那么不要试图把它放在一个variables中,直接使用它:

     rsync --rsh='ssh -p2222' $RESTOFOPTS "$BACKDIR" "$USER@$DEST:$DESTDIR" 
  3. 如果这两种情况都不适用,则使用数组而不是普通variables:

     OPTS=(-x --delete --inplace) if [[ "$rsync_version" == 2.* ]]; then OPTS+=(-aE) else OPTS+=(-aNHX) fi if [[ -n "$using_rsh" ]]; then OPTS+=('--rsh=ssh -p2222') fi rsync "${OPTS[@]}" "$BACKDIR" "$USER@$DEST:$DESTDIR" 

要保留variables中的引号和空格,需要引用该variables的引用:

 rsync "$OPTS" "$BACKDIR" "$USER@$DEST:$DESTDIR" 

我猜你的rsh选项应该与rsync的-e (resp --rsh rsh )标志一起使用,以便rsync知道使用ssh连接的自定义端口。 你的命令是这样的:

 ssh -some -opts --rsh="ssh -p222" fromdir/ user@host:/todir 

当rsync执行时,ssh -p222部分的引号可能会丢失。 你可以尝试像这样定义rshvariables:

 rsh='"ssh -p222"' 

以便在执行期间(字面上包括双引号)评估为“ssh -p222”。

一种select是从脚本中的$ IFS中删除“空格”:

 #!/bin/bash IFS=$'\n\t' ... rsync $OPTS $BACKDIR $USER@$DEST:$DESTDIR 

Bash将会像大多数程序员所期望的那样工作,因为空格将不再被用作variables中的字段分隔符。