Передача переменных в удаленной команде ssh

103

Я хочу иметь возможность запускать команду со своего компьютера с помощью ssh и передавать переменную среды $BUILD_NUMBER

Вот что я пытаюсь:

ssh pvt@192.168.1.133 '~/tools/myScript.pl $BUILD_NUMBER'

$BUILD_NUMBER установлен на машине, выполняющей вызов ssh, и поскольку переменная не существует на удаленном хосте, она не обрабатывается.

Как передать значение $BUILD_NUMBER?

Фергал
источник
1
не имеющий отношения к Гудзону, удалил тег. (Хадсон просто создает переменную)
Peter Schuetze

Ответы:

198

Если вы используете

ssh pvt@192.168.1.133 "~/tools/run_pvt.pl $BUILD_NUMBER"

вместо того

ssh pvt@192.168.1.133 '~/tools/run_pvt.pl $BUILD_NUMBER'

ваша оболочка будет интерполировать $BUILD_NUMBERперед отправкой командной строки на удаленный хост.

Сарнольд
источник
8
Если кто-то ДОЛЖЕН использовать одинарные кавычки, чтобы команда, включенная в кавычки, не оценивалась локально, то они должны использовать «$ VARIABLE». Пример: ssh pvt@192.168.1.133 '~ / tools / run_pvt.pl "' $ BUILD_NUMBER '"'
dr.doom
3
не знал, что bash по-разному реагирует на одинарные и двойные кавычки. Благодарность!
Silgon
1
разработчики ядра linux должны гореть в аду
goldstar
@goldstar, обратите внимание, что разница между одинарными и двойными кавычками в оболочке появилась раньше Linux на десятилетия.
sarnold
3
PSA: если ваша строка содержит пользовательский ввод, это очень плохая идея и может открыть вас для атак путем внедрения кода.
Брайан МакКатчон,
27

Переменные в одинарных кавычках не оцениваются. Используйте двойные кавычки:

ssh pvt@192.168.1.133 "~/tools/run_pvt.pl $BUILD_NUMBER"

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

Стивен
источник
3

(Этот ответ может показаться излишне сложным, но, насколько мне известно, он легко расширяемый и надежный в отношении пробелов и специальных символов.)

Вы можете вводить данные прямо через стандартный ввод sshкоманды и readиз удаленного места.

В следующем примере

  1. индексированный массив заполняется (для удобства) именами переменных, значения которых вы хотите получить на удаленной стороне.
  2. Для каждой из этих переменных мы даем sshстроку с завершающим нулем, в которой указывается имя и значение переменной.
  3. В самой shhкоманде мы просматриваем эти строки, чтобы инициализировать необходимые переменные.
# Initialize examples of variables.
# The first one even contains whitespace and a newline.
readonly FOO=$'apjlljs ailsi \n ajlls\t éjij'
readonly BAR=ygnàgyààynygbjrbjrb

# Make a list of what you want to pass through SSH.
# (The “unset” is just in case someone exported
# an associative array with this name.)
unset -v VAR_NAMES
readonly VAR_NAMES=(
    FOO
    BAR
)

for name in "${VAR_NAMES[@]}"
do
    printf '%s %s\0' "$name" "${!name}"
done | ssh user@somehost.com '
    while read -rd '"''"' name value
    do
        export "$name"="$value"
    done

    # Check
    printf "FOO = [%q]; BAR = [%q]\n" "$FOO" "$BAR"
'

Выход:

FOO = [$'apjlljs ailsi \n ajlls\t éjij']; BAR = [ygnàgyààynygbjrbjrb]

Если они вам не нужны export, вы сможете использовать declareвместо export.

Действительно упрощенная версия (если не нужна расширяемость, имеет одну переменный процесс и т.д.) будет выглядеть следующим образом :

$ ssh user@somehost.com 'read foo' <<< "$foo"
Алиса М.
источник
2

Список допустимых переменных среды на SSHD по умолчанию включает LC_*. Таким образом:

LC_MY_BUILDN="1.2.3" ssh -o "SendEnv LC_MY_BUILDN" ssh-host 'echo $LC_MY_BUILDN'
1.2.3
Алекс Стрейджис
источник
1

Также можно явно передавать переменные среды через ssh. Это требует некоторой настройки на стороне сервера, так что это не универсальный ответ.

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

На сервере отредактируйте sshd_configфайл, как правило, /etc/ssh/sshd_configи добавьте AcceptEnvдирективу, соответствующую переменным, которые вы хотите передать. Смотрите man sshd_config. В моем случае я хочу передать переменные в резервную копию borg, поэтому я выбрал:

AcceptEnv BORG_*

Теперь на клиенте используйте -o SendEnvвозможность отправки переменных среды. Следующая командная строка устанавливает переменную среды, BORG_SECRETа затем помечает ее для отправки на клиентский компьютер (вызываемый backup). Затем он запускается printenvтам и фильтрует вывод для переменных BORG:

$ BORG_SECRET=magic-happens ssh -o SendEnv=BORG_SECRET backup printenv | egrep BORG
BORG_SECRET=magic-happens
ТВЕ
источник
Вы можете «протащить» свои переменные, используя настройки на стороне сервера по умолчанию, см. Мой ответ . Суть в том, что конфигурация OpenSSHd по умолчанию включает LC_*разрешенные для отправки переменные, поэтому просто используйте $LC_TvE_fooили $LC_BORG_SECRETпросто убедитесь, что вы не «сталкиваетесь» со встроенной переменной.
Alex Stragies
0

Как уже было сказано ранее, вам не нужно устанавливать переменную среды на удаленном хосте. Вместо этого вы можете просто выполнить мета-расширение на локальном хосте и передать значение удаленному хосту.

ssh pvt@192.168.1.133 '~/tools/run_pvt.pl $BUILD_NUMBER'

Если вы действительно хотите установить переменную среды на удаленном хосте и использовать ее, вы можете использовать envпрограмму

ssh pvt@192.168.1.133 "env BUILD_NUMBER=$BUILD_NUMBER ~/tools/run_pvt.pl \$BUILD_NUMBER"

В этом случае это немного перебор, и обратите внимание

  • env BUILD_NUMBER=$BUILD_NUMBER делает ли мета-расширение на локальном хосте
  • BUILD_NUMBERпеременная удаленной среды будет использоваться
    удаленной оболочкой
Жиль Гуаилларде
источник
-2

Экранируйте переменную, чтобы получить доступ к переменным вне сеанса ssh: ssh pvt@192.168.1.133 "~ / tools / myScript.pl \ $ BUILD_NUMBER"

Сара Грюнайзен
источник
2
Этим не достигается то, о чем спрашивается.
Патрик
2
с точки зрения оболочки '$FOO'эквивалентно "\$FOO". вопрос был в том, «как передать переменную оболочки с помощью SSH?». Как уже было сказано @PatrickTrentin, это неправильный ответ, потому что тогда BUILD_NUMBERпеременная среды не устанавливается удаленно.
Gilles Gouaillardet