Передача змінних у віддалену команду ssh


99

Я хочу мати змогу запустити команду зі своєї машини за допомогою ssh та пройти через змінну середовища $BUILD_NUMBER

Ось що я намагаюся:

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

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

Як передати значення $BUILD_NUMBER?


1
не пов'язаний з Гудзоном, видалив тег. (Хадсон просто створює змінну)
Пітер Шуетце

Відповіді:


188

Якщо ви використовуєте

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: якщо ваш рядок містить введення користувача, це дуже погана ідея, і це може відкрити вас до атак введення коду.
Brian McCutchon

27

Змінні в одиничних лапках не оцінюються. Використовуйте подвійні лапки:

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

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


2

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

Ви можете подавати дані прямо через стандартний ввід 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

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використовуватиме змінну віддаленого середовища

0

Також можна явно передавати змінні середовища через ssh. Це вимагає певної настройки на стороні сервера, тому це не універсальна відповідь.

У моєму випадку я хотів передати ключ шифрування резервного репозиторію команді на сервері резервного копіювання, не зберігаючи там ключ, але зауважте, що будь-яка змінна середовище видно в ps! Рішення передачі ключа на stdin також би спрацювало, але я вважав це занадто громіздким. У будь-якому випадку, ось як передати змінну середовища через ssh:

На сервері відредагуйте sshd_configфайл, як правило, /etc/ssh/sshd_configі додайте AcceptEnvдирективу, що відповідає змінним, які ви хочете передати. Див man sshd_config. У моєму випадку я хочу передати змінні в borg backup, тому я вибрав:

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просто переконайтеся, що ви не «стикаєтесь» із вбудованою змінною.
Олексій Страггій

-2

Уникніть змінної, щоб отримати доступ до змінних поза сеансом ssh: ssh pvt@192.168.1.133 "~ / tools / myScript.pl \ $ BUILD_NUMBER"


2
Це не дозволяє досягти того, про що задається питання.
Патрік Трентін,

2
з точки зору оболонки, '$FOO'еквівалентно "\$FOO". питання було "як передати змінну оболонки за допомогою SSH?". Як уже зазначав @PatrickTrentin, це не правильна відповідь, оскільки тоді BUILD_NUMBERзмінна середовища не встановлюється віддалено.
Gilles Gouaillardet
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.