Когда я ssh'ing, как я могу установить переменную среды на сервере, которая меняется от сеанса к сеансу?


92

Когда я sshзахожу на сервер, как я могу передать переменную окружения от клиента к серверу? Эта переменная окружения изменяется между различными вызовами ssh, поэтому я не хочу перезаписывать $HOME/.ssh2/environmentкаждый раз, когда выполняю ssh-вызов. Как я могу это сделать?


2
Ваш вопрос должен быть более конкретным.
Игнасио Васкес-Абрамс

3
Вопрос был достаточно ясен для меня. Однако со sshстраницы руководства я не вижу другого способа сделать это, кроме установки переменной вручную после входа на сервер, если только вы не изменили ~ / .ssh2 / environment.
Гариджон

Это разные переменные каждый раз? Или другое значение?
Деннис Уильямсон


1
И наоборот, так как это уже популярнее. Неважно, что он старше.
Кенорб

Ответы:


110

Конечно, вы можете установить переменную окружения внутри команды, однако вы должны быть осторожны с цитированием: помните, что ваша оболочка будет анализировать вашу локальную командную строку, и тогда удаленная оболочка будет использовать строку получает.

Если вы хотите, чтобы переменная получала то же значение на сервере, что и на клиенте, попробуйте SendEnvпараметр:

ssh -o SendEnv = MYVAR server.example.com mycommand

Это требует поддержки со стороны сервера. В OpenSSH имя переменной должно быть авторизовано в /etc/sshd_config.

Если сервер допускает только определенные имена переменных, вы можете обойти это; например, обычная настройка позволяет LC_*, и вы можете сделать следующее:

ssh -o SendEnv = LC_MYVAR server.example.com 'MYVAR = $ LC_MYVAR; unset LC_MYVAR; экспорт MYVAR; МояКоманда»

Если даже LC_*это не вариант, вы можете передать информацию в TERMпеременную окружения, которая всегда копируется (однако может быть ограничение длины). Вам все равно придется убедиться, что удаленная оболочка не ограничивает TERMпеременную для обозначения известного типа терминала. Передайте -tпараметр ssh, если вы не запускаете удаленную интерактивную оболочку.

env TERM = "дополнительная информация: $ TERM" ssh -t server.example.com 'MYVAR = $ {TERM%: *}; TERM = $ {TERM ## *:}; экспорт MYVAR; МояКоманда»

Другая возможность - определить переменную непосредственно в команде:

ssh -t server.example.com 'export MYVAR = "дополнительная информация"; МояКоманда»

Таким образом, если передать локальную переменную:

ssh -t server.example.com 'export MYVAR =' "'$ LOCALVAR'" '; МояКоманда»

Однако остерегайтесь проблем с цитированием: значение переменной будет интерполировано непосредственно во фрагмент оболочки, выполненный на удаленной стороне. Последний пример выше предполагает, что $LOCALVARне содержит каких-либо одинарных кавычек ( ').


2
Большое спасибо, я был в ярости, что глупые переменные LC_ * экспортируются в ssh, и твой ответ указал мне, где искать. Я просто должен отключить это в ~ / .ssh / config
akostadinov

1
Я нахожусь в ситуации с оригинальным постером, но переменная, которую я хотел переслать, это TERM, поэтому я немного озадачен вашим ответом. Была ли эта автоматическая пересылка TERM отключена в последних версиях OpenSSH?
Doub

1
@Doub По умолчанию все системные переменные на стороне сервера отклоняются с AcceptEnvуказанием директив по sshd_configжеланию администратора. Но TERMлечится особо, насколько я знаю, нет способа отфильтровать его на стороне сервера (он устанавливается в среде оболочки независимо от какого-либо параметра конфигурации). Вы уверены, что нет сценария профиля, переопределяющего его (как /etc/profileили ~/.profileили ~/.bashrc)?
Жиль

2
@Gilles: я проверил это снова, и если я явно не добавлю TERM в свою директиву AcceptEnv, TERM не передается. Я не открываю оболочку, а запускаю команду напрямую, например: "ssh -o SendEnv = TERM shell.example.com env". Это печатает все переменные среды, и TERM появляется, только если он находится в SendEnv на клиенте и AcceptEnv на сервере. Если я запускаю «ssh -o SendEnv = TERM shell.example.com echo \ $ {TERM}» без AcceptEnv или SendEnv, он печатает «тупой», который я не уверен, откуда он приходит (env даже не список СРОК в этом случае).
Doub

7
@ Сомневаюсь. TERMпередается только в том случае, если клиент просит сервер выделить tty. Если на удаленной стороне нет терминала, его бесполезно передавать TERM. Когда вы указываете команду, если вы хотите иметь терминал на удаленной стороне, вам нужна -tопция командной строки (или RequestTTYin ~/.ssh/config).
Жиль

12

Если вы можете администрировать целевой хост, вы можете настроить sshd, чтобы разрешить передачу локальных переменных среды на целевой хост.

Со страницы руководства sshd_config:

 PermitUserEnvironment
     Specifies whether ~/.ssh/environment and environment= options in
     ~/.ssh/authorized_keys are processed by sshd.  The default is
     "no".  Enabling environment processing may enable users to bypass
     access restrictions in some configurations using mechanisms such
     as LD_PRELOAD.

конфигурация sshd обычно живет в /etc/ssh/sshd_config


7
Очень полезно знать, что по умолчанию установлено «нет»!
Ятанизм

6

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

ssh remote.host my_command

Ты можешь сделать это:

ssh remote.host env ENV_VAR=$ENV_VAR my_command

"вероятно"? Я хотел бы прочитать это, прежде чем пытаться ответить на этот вопрос. Не работал для меня
Тишма

1
Хотите уточнить ошибки и т.д.?
фото

1
@pioto Можно цитировать, например, если в ENV_VAR есть пробелы
Мартин С. Мартин,

На Mac у вас должна быть опция -t для интерактивной версии, иначе она выглядит застрявшей. Так что это может сработать: $ ssh -t remote.host env ENV_VAR = $ ENV_VAR my_command
muenalan

3

Ответ @ emptyset (который мне не помог) привел меня к такому ответу:

Вы можете добавить эту команду в свой ~/.ssh/authorized_keysфайл:

command="/usr/bin/env VARIABLE=<something> $SHELL" ssh-rsa <key>

export VARIABLE=<something>был немедленно завершен, и SSH-соединение было закрыто (заблокировав меня из-за сервера), в то время как /usr/bin/env ... $SHELLоболочка по умолчанию будет работать с измененной средой.


Это просто зависает при входе в систему для меня. Когда я удаляю его, SSH возвращается в нормальное состояние, и я получаю свою обычную оболочку для входа.
Ник Свитинг

@NickSweeting Вы пробовали, может быть, заменить $SHELLреальную оболочку? Также проверьте, что / usr / bin / env существует на сервере. Однако решение не является идеальным: я заметил, что оно зависало, когда я хотел использовать scpили встроенную команду.
madprog

Да, это было первое, что я попробовал. К сожалению, так и не получил его на работу, в конечном итоге включить PermitUserEnvironment yesи использовать environment="..."вместо command="...".
Ник Свитинг

Это хорошо работает для меня.
г-н Тао

3

На вашем локальном клиенте, в вашем ~/.ssh/configвы можете добавить SetEnv, например,

Host myhost
  SetEnv FOO=bar

Примечание: проверьте man ssh_config.

Затем на сервере обязательно разрешите клиенту передавать определенные переменные окружения в вашем /etc/ssh/sshd_configконфигурационном файле:

AcceptEnv LANG LC_* FOO BAR*

Примечание: проверьте man sshd_config.


1

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

command="export VARIABLE=<something>" ssh-rsa <key>

Посмотрите на эту ссылку в разделе « Принудительное командование» для более подробной информации.


1
Я пробовал это, но это не работает. Он запускает команду и завершает работу, поэтому интерактивный сеанс отсутствует. Это нормальное поведение? Если это так, это может быть полезно, если все, что вы хотите сделать, это позволить определенному ключу вызвать определенную команду, но если вы хотите передать информацию, которая используется в сеансе (как говорится в вопросе), тогда это бесполезно для этой цели , Там нет сессии.
иконоборчество

1

Я делал пользовательскую сборку OpenSSH для устройства с cramfs в домашнем каталоге и / etc (Cram FS только для чтения), поэтому ~ / .ssh / environment не будет работать без перестройки всей FS, и они были развернуты на местах устройства (встроенные системы, следовательно, использование CRAMFS). Вы можете указать в sshd_config местоположение файла authroized_keys, но по какой-то причине среда работает только для переменных среды в ~ / .ssh / authroized_keys. Редактирование / etc / profile не было вариантом, и мне пришлось загружать ssh в нестандартный каталог. В session.c после child_set_env (... "MAIL" ...) просто добавьте переменные окружения, которые вам нужны (это хак, я знаю ...), но просто добавьте, что кому-то нужны жестко закодированные envs для сеанса, если вы компиляция из источника вы можете сделать это. TGI-FLOSS


0

только одна простая команда:

ssh -t your_host_or_ip 'export some_var_name=whatever_you_want; bash'
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.