Понимание проблемы: Что происходит с вашей текущей командой, 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