Назад | Перейти на главную страницу

Ошибка в сценарии 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.

Длинный ответ: сложно поместить команды (или части команд) в переменные, а затем вернуть их в неизменном виде. Когда оболочка расширяет переменную в командной строке, если переменная была заключена в двойные кавычки, она не анализируется (см. Ответ @Dennis Williamson); если он не был заключен в кавычки, пробелы в нем анализируются как разрывы аргументов, но кавычки и escape-символы не анализируются (вот почему вы получили ошибку о буквальном значке кавычек в одном из аргументов для rsync). В любом случае помещение в кавычки значения переменной не дает ничего полезного.

Однако есть несколько способов исправить ваш скрипт, в зависимости от сложности OPTS:

  1. Если --rsh - единственное, что есть в OPTS, заключите его в двойные кавычки (как в ответе Денниса Уильямсона):

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

    (Обратите внимание на двойные кавычки вокруг других аргументов: это необходимо для предотвращения неправильного анализа, если они содержат пробелы, и, как правило, это хорошая гигиена сценариев.)

  2. Если содержимое OPTS постоянно (или, по крайней мере, часть --rsh), не пытайтесь поместить его в переменную, просто используйте ее напрямую:

    rsync --rsh='ssh -p2222' $RESTOFOPTS "$BACKDIR" "$USER@$DEST:$DESTDIR"
    
  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"
    

Чтобы сохранить кавычки и пробелы в переменной, вам нужно заключить переменную в кавычки, когда на нее ссылаются:

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

Я думаю твой rsh параметр следует использовать с rsync -e (соотв. --rsh), чтобы rsync знал, что нужно использовать настраиваемый порт для ssh-соединения. Ваша команда выглядит так:

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

Может случиться так, что кавычки вокруг части 'ssh -p222' просто отсутствуют при выполнении rsync. Вы можете попробовать определить rsh вместо этой переменной:

rsh='"ssh -p222"'

так что во время выполнения он оценивается как «ssh -p222» (буквально, включая двойные кавычки).

Один из вариантов - удалить "пробел" из $ IFS в вашем скрипте:

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

В этом случае Bash будет вести себя так, как ожидает большинство программистов, поскольку пробелы больше не будут использоваться в качестве разделителей полей внутри переменных.