Bash rsync 脚本中的错误

Hum*_*ger 3 bash rsync

bash 脚本具有以下行

    rsync $OPTS $BACKDIR $USER@$DEST:$DESTDIR     
Run Code Online (Sandbox Code Playgroud)

但选项之一是rsh='ssh -p2222' 它抱怨:

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

但是当我将脚本更改为:

    echo rsync $OPTS $BACKDIR $USER@$DEST:$DESTDIR     
Run Code Online (Sandbox Code Playgroud)

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

请指教

Gor*_*son 5

简短回答:参见BashFAQ #50

长答案:将命令(或命令的一部分)放入变量中,然后将它们原封不动地取出来是很复杂的。当 shell 在命令行上扩展一个变量时,如果该变量是双引号,则不会对其进行解析(请参阅 @Dennis Williamson 的回答);如果它不在引号中,则其中的空格会被解析为参数中断,但不会解析引号和转义符(这就是为什么在 rsync 的 args 中出现关于文字引号的错误的原因)。在任何一种情况下,在变量的值中加上引号都没有任何用处。

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

  1. 如果 --rsh 是 OPTS 中唯一的内容,则用双引号引用它(如丹尼斯·威廉姆森的回答):

    OPTS='--rsh=ssh -p2222'
    rsync "$OPTS" "$BACKDIR" "$USER@$DEST:$DESTDIR"
    
    Run Code Online (Sandbox Code Playgroud)

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

  2. 如果 OPTS 的内容是常量(或者至少 --rsh 部分是),那么不要尝试将其放入变量中,直接使用即可:

    rsync --rsh='ssh -p2222' $RESTOFOPTS "$BACKDIR" "$USER@$DEST:$DESTDIR"
    
    Run Code Online (Sandbox Code Playgroud)
  3. 如果这些简单情况都不适用,请使用数组而不是普通变量:

    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"
    
    Run Code Online (Sandbox Code Playgroud)