Неожиданное поведение при запуске удаленного скрипта - PullRequest
0 голосов
/ 21 ноября 2018

Я пытаюсь написать скрипт, который запускается на удаленной машине.

Поскольку этот скрипт сложный, я разбил его части на функции, которые затем копировал в скрипт, используя typeset.

Когда я запускаю скрипт, я получаю следующую ошибку:

bash: -c: line 4: syntax error: unexpected end of file

Однако неожиданного конца файла нет!Я гарантировал, что все if s имели fi s, все { имели } и т. Д.

Я гарантировал, что все отступы используют табуляции (и пробелы), и что символы новой строкипоследовательный.

Я сократил код до минимального примера.Кажется, что для того, чтобы функция была действительной, она должна заканчиваться такой конструкцией, как if fi или while done.

Вот что не работает.

func() {
  ls ~/
}

ssh -A -T user@machine_ip '
'$(typeset -f func)'
func
'

Строка 4 совпадает с окончанием } функции func (считая строк после ssh -A -T..., поскольку эта ошибка происходит на удаленном компьютере).

Тем не менее, если мыдобавьте конструкцию в конец функции, домашний каталог будет напечатан, как и ожидалось.

func() {
    ls ~/
    if [[ 1 ]]; then
      echo "Hello"
    fi
}

или

func() {
    ls ~/
    while false; do
        echo "Here"
    done
}

Вывод typeset -f func равен

func () 
{ 
    ls --color=auto ~/;
    if [[ -n 1 ]]; then
        echo "Hello";
    fi
}

Я использую Ubuntu 18.04 LTS, удаленный компьютер работает с Centos 6.

Ответы [ 2 ]

0 голосов
/ 21 ноября 2018

Прежде всего, то, как вы используете кавычки, не имеет смысла для меня.

ssh -A -T user@machine_ip '
'$(typeset -f func)'
func
'

2 first 'просто повторяет пустую строку.(2-й 'закрыть 1-ю. логику?)

В любом случае.

$(typeset -f func)
func

приведенный выше код будет выполнять func 2 раза.По крайней мере, вот как это работает для меня

....

0 голосов
/ 21 ноября 2018

Потому что bash играет с пробелами, если вы позволите.Позвольте мне объяснить:

$(typeset -f func) оценит typeset -f func и вставит его вывод в текущую командную строку.Если не заключено в кавычки, он также будет сегментирован на параметры, которые будут иметь побочный эффект свертывания всех пробелов в одно пространство.Таким образом, если typeset -f func напечатает (как это происходит в моей системе)

func () 
{ 
    /bin/ls --color=auto ~/
}

, то, что вы получите с $(typeset -f func), будет

func () { /bin/ls --color=auto ~/ }

(попробуйте echo $(typeset -f func), если вы неНе верьте мне: D)

Теперь bash очень стесняется принимать замаскированный код.Например, вы можете знать, что это не грамматически:

if true then echo "yes" fi

и это:

if true; then echo "yes"; fi

Таким же образом закрывающая скобка определения функции является разборчивой.Таким образом, это работает:

func () { /bin/ls --color=auto ~/; }

, но это не так:

func () { /bin/ls --color=auto ~/ }

По какой-то причине bash подходит для ключевого слова перед скобкой:

func () { /bin/ls --color=auto ~/; if [[ -n 1 ]]; then echo "Hello"; fi }
func () { /bin/ls --color=auto ~/; while false; do echo "Here"; done }

Чтобы бороться с этим ... попробуйте не посылать материал из командной строки, который искажает ваш пробел, но из перенаправления:

ssh -A -T user@machine_ip < <(typeset -f func; echo func)

Или, проще всего, предотвратить bash искажениепробелов в двойных кавычках:

ssh -A -T user@machine_ip "$(typeset -f func)
func"
...