Очень важно, это зависит от PowerShell.
Существует множество ответов на этот вопрос, ответом на которые является использование одинарных кавычек вместо двойных.
например ssh me@server "invalid_program; echo $?"
-> ssh me@server 'invalid_program; echo $?'
Это невозможно в Windows в PowerShell с OpenSH. https://stackoverflow.com/a/75740191/8652920
Учитывая, что существует ограничение: мне нужно использовать ssh только с двойными кавычками, есть ли способ заставить расширение переменной среды происходить на удаленном компьютере?
Вы можете попробовать это на своем PowerShell.
PS C:\...> ssh me@remote "beep; echo $?"
Warning: Permanently added 'remote' (ECDSA) to the list of known hosts.
bash: beep: command not found
True
Стандартный вывод должен быть 127, а не True.
% ssh me@remote 'beep; echo $?'
Warning: Permanently added 'remote' (ED25519) to the list of known hosts.
127
bash: beep: command not found
Предисловие:
Это [с использованием одинарных кавычек] невозможно в Windows в PowerShell с OpenSH.
В PowerShell (в отличие от cmd.exe
/пакетных файлов/вызовов без оболочки) использование '...'
при вызове внешних программ, таких как ssh
, работает даже в Windows, поскольку PowerShell преобразует такие аргументы в аргументы, заключенные в "..."
(двойные кавычки) за кулисами. , предполагая, что они содержат пробелы.[1]
Действительно, использование '...'
(строка в одинарных кавычках) — самое простое решение в вашем случае — см. следующий раздел.
$
— это метасимвол как в PowerShell, так и в POSIX-совместимых оболочках, таких как bash
, и в обеих оболочках "..."
— это расширяемая, т. е. интерполирующая строка.
Таким образом, в ssh me@remote "beep; echo $?"
PowerShell заранее расширяет $?
,[2] используя текущее значение , его определение $? , которое является логическим значением.
Чтобы предотвратить нежелательную предварительную интерполяцию:
Либо: используйте ssh me@remote "beep; echo `$?"
, т. е. экранируйте встроенный $
, используя escape-символ PowerShell, `
(так называемый обратный апостроф).
Или: используйте дословную строку ('...'
), к которой по задумке не применяется интерполяция:ssh me@remote 'beep; echo $?'
[1] That is, PowerShell passes arguments that do not contain spaces unquoted on the process command line constructed behind the scenes. Unfortunately, this can break invocation of batch files (*.cmd
, *.bat
), because cmd.exe
, the batch-file interpreter - inappropriately - parses its command line as if it had been passed from inside a cmd.exe
session. Thus, an invocation from PowerShell such as .\foo.cmd 'a&b'
breaks and requires awkward workarounds. GitHub issue #15143 is a proposal to prevent such problems, but, regrettably, it died from neglect.
Note that in Unix-like environments this point is moot, because there are no process command lines - argument are invariably passed as an array of verbatim strings.
[2] It follows from the above that if you were to run this command from a POSIX-compatible shell (i.e. from a Unix environment), undesired up-front interpolation would occur too, except that a number would be interpolated, namely the most recently executed command's exit code, which is what $?
reflects in those shells.
я не уверен, что это было неясно, но я просто сделал C:\...>
, чтобы скрыть структуру моего каталога и имя репозитория, поскольку материалы, над которыми я работаю, теоретически защищены соглашениями о конфиденциальности и тому подобным, но путь к каталогу не имеет к этому никакого отношения. вопрос в любом случае
@notacorn, мне неясно, как ваш комментарий связан с моментами, которые я высказал в этом ответе. Независимо, пожалуйста, ознакомьтесь с предисловием, которое я добавил к ответу, в котором устраняется заблуждение о том, что невозможно использовать аргументы, заключенные в '...'
, при вызове внешних программ в PowerShell.
Я думаю, мне просто нужно было уточнить, что означает ...
, что, похоже, означает «что угодно», так что теперь это стало ясно.
Понятно, @notacorn. Да, как и вы в вопросе, я использовал ...
в качестве заполнителя для чего-то, особенности которого не имеют отношения к объясняемому. Я часто использую '...'
/"..."
для обозначения строк в одинарных/двойных кавычках, потому что их легко распознать визуально. После этого разъяснения я думаю, что этот ответ отвечает на ваш вопрос в том виде, в каком он задан, и решает вашу проблему.
вау, это потрясающе, спасибо!!
Рад слышать, что это помогло, @notacorn; Не за что. Спасибо за приятный отзыв.
В качестве отступления:
$?
— это переменная оболочки (только), а не переменная среды, как в POSIX-совместимых оболочках, так и в PowerShell. Переменные оболочки видны только текущему процессу оболочки, а копии не наследуются дочерними процессами (за ограниченным исключением подоболочек в POSIX-совместимых оболочках). В POSIX-совместимых оболочках переменные оболочки и переменные среды упоминаются с использованием одного и того же синтаксиса (например,$FOO
; env. vars. помечаются как таковые, обычно с помощьюexport
), тогда как PowerShell имеет отдельное пространство имен для переменных среды (например,$env:FOO
).