Учти это:
$ ssh localhost bash -c 'export foo=bar'
terdon@localhost's password:
declare -x DBUS_SESSION_BUS_ADDRESS="unix:path=/run/user/1000/bus"
declare -x HOME="/home/terdon"
declare -x LOGNAME="terdon"
declare -x MAIL="/var/spool/mail/terdon"
declare -x OLDPWD
declare -x PATH="/usr/bin:/bin:/usr/sbin:/sbin"
declare -x PWD="/home/terdon"
declare -x SHELL="/bin/bash"
declare -x SHLVL="2"
declare -x SSH_CLIENT="::1 55858 22"
declare -x SSH_CONNECTION="::1 55858 ::1 22"
declare -x USER="terdon"
declare -x XDG_RUNTIME_DIR="/run/user/1000"
declare -x XDG_SESSION_ID="c5"
declare -x _="/usr/bin/bash"
Почему экспорт переменной в bash -c
сеансе, запущенном через ssh, приводит к этому списку declare -x
команд (насколько я могу судить, список экспортируемых переменных в данный момент)?
Запуск того же самого без без bash -c
этого не делает:
$ ssh localhost 'export foo=bar'
terdon@localhost's password:
$
И не произойдет, если мы не сделаем export
:
$ ssh localhost bash -c 'foo=bar'
terdon@localhost's password:
$
Я проверил это, выполнив sshing с одного компьютера с Ubuntu на другой (на обоих запущен bash 4.3.11) и на компьютере Arch, выполняя sshing себе, как показано выше (версия bash 4.4.5).
Что тут происходит? Почему экспорт переменной внутри bash -c
вызова производит этот вывод?
export
. Zsh делает то же самое.export
, я пытаюсь понять, что происходит. Я отредактирую, чтобы уточнить, что это происходит только при экспорте.export
запуска в одиночку? Этого я не поняла.foo=bar
не появляется в списке.Ответы:
Когда вы запускаете команду
ssh
, она вызывается$SHELL
с-c
флагом:Итак, на
ssh remote_host "bash -c foo"
самом деле будет работать:Теперь, так как команда, которую вы запускаете (
export foo=bar
), содержит пробелы и не содержит правильных кавычек для формирования целого, командаexport
принимается за команду, которую нужно выполнить, а остальные сохраняются в массиве позиционных параметров. Это означает, чтоexport
запускается иfoo=bar
передается ему как$0
. Окончательный результат такой же, как бегПравильная команда будет:
источник
ssh
объединяет аргументы с пробелами и интерпретирует их как оболочка входа удаленного пользователя, поэтому:ssh
просит удаленную оболочку интерпретироватьКоманда (в действительности, если удаленный хост Unix-подобный, он будет работать с удаленной оболочкой с
the-shell
,-c
а вbash -c export foo=bar
качестве аргументов).Большинство снарядов будет интерпретировать эту командную строку , как работает
bash
команда сbash
,-c
,export
и вfoo=bar
качестве аргументов (так работать ,export
пока$0
содержитfoo=bar
) , а вы хотите , чтобы запустить его сbash
,-c
и вexport foo=bar
качестве аргументов.Для этого вам нужно использовать командную строку, например:
(или:
для этого имеет значение) так что:
Командная строка передается в удаленную оболочку. Эта командная строка будет интерпретироваться большинством оболочек , как работает
bash
команда сbash
,-c
а вexport foo=bar
качестве аргументов. Обратите внимание, что с помощьюне будет работать, если оболочка входа удаленного пользователя была
rc
или,es
например,"
не является специальным оператором цитирования. Одиночные кавычки являются наиболее переносимыми операторами кавычек (хотя есть некоторые различия в том, как они интерпретируются между оболочками, см. Как выполнить произвольную простую команду над ssh, не зная оболочки входа удаленного пользователя? Для получения дополнительной информации).источник