Как сохранить параметр с пробелами при запуске файла удаленного скрипта с SSH? - PullRequest
0 голосов
/ 25 ноября 2018

Я обнаружил, что когда я запускаю скрипт локально, например

./run.sh a "b c"

, он идентифицирует два параметра при использовании «$ @» в run.sh.Однако при использовании на удаленной машине через ssh это не так.

ssh user@host ./run.sh a "b c"

Так как же мне этого добиться?

Ответы [ 2 ]

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

Понимание проблемы: Что происходит с вашей текущей командой, ssh user@host ./run.sh a "b c", так это то, что локальная оболочка анализирует команду на «слова» (применяя и удаляя любые кавычки и / или экранированные символы, которые она видит), и получает «ssh"," user@host "," ./run/sh "," a "и" b c ".Он принимает первое (ssh) в качестве команды и передает остальное ей в качестве аргументов.ssh принимает "user@host" как ssh, и (вот что критично) просто склеивает (разделенные пробелами) удаленную команду для запуска.Это дает "./run.sh a b c" в качестве удаленной команды.Затем он передается в удаленную оболочку, которая (поскольку кавычки теперь отсутствуют) интерпретирует "a", "b" и "c" как отдельные аргументы.

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

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

Вот простойЧистый способ сделать это:

ssh user@host './run.sh a "b c"'

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

ssh user@host "./run.sh a \"b c\""

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

ssh user@host ./run.sh a \"b c\"

На самом деле существует множество способов сделать это, комбинируя различные опции цитирования / экранирования на локальных и удаленных оболочках:

ssh user@host ./run.sh a '"b c"'
ssh user@host "./run.sh a 'b c'"
ssh user@host './run.sh a b\ c'
ssh user@host ./run.sh a b\\ c

Кстати, вВообще, echo что-то - действительно плохой способ выяснить, как анализируются ваши аргументы, потому что он просто склеивает свои аргументы вместе с пробелами между ними.Но поскольку это то же самое, что ssh делает при создании удаленной команды, вы можете заменить ssh user@host на echo, чтобы увидеть, что в действительности будет передаваться удаленной оболочке:

$ echo ./run.sh a "b c"
./run.sh a b c
$ echo './run.sh a "b c"'
./run.sh a "b c"
$ echo "./run.sh a \"b c\""
./run.sh a "b c"
$ echo "./run.sh a 'b c'"
./run.sh a 'b c'
$ echo ./run.sh a b\\ c
./run.sh a b\ c
0 голосов
/ 25 ноября 2018

Попробуйте это:

ssh user@host 'bash -c "./run.sh a \"b c\""'

...