Przekazywanie zmiennych w zdalnym poleceniu ssh

103

Chcę mieć możliwość uruchomienia polecenia z mojego komputera za pomocą ssh i przejścia przez zmienną środowiskową $BUILD_NUMBER

Oto, czego próbuję:

ssh [email protected] '~/tools/myScript.pl $BUILD_NUMBER'

$BUILD_NUMBER jest ustawiana na maszynie wykonującej wywołanie ssh, a ponieważ zmienna nie istnieje na zdalnym hoście, nie jest pobierana.

Jak przekazać wartość $BUILD_NUMBER?

Fergal
źródło
1
niezwiązany z Hudsonem, usunął tag. (Hudson właśnie tworzy zmienną)
Peter Schuetze

Odpowiedzi:

197

Jeśli użyjesz

ssh [email protected] "~/tools/run_pvt.pl $BUILD_NUMBER"

zamiast

ssh [email protected] '~/tools/run_pvt.pl $BUILD_NUMBER'

Twoja powłoka interpoluje $BUILD_NUMBERprzed wysłaniem polecenia do zdalnego hosta.

sarnold
źródło
8
Jeśli ktoś MUSI używać pojedynczych cudzysłowów, aby polecenie zawarte w cudzysłowach nie było oceniane lokalnie, powinien użyć „$ VARIABLE” ”. Przykład: ssh [email protected] '~ / tools / run_pvt.pl "' $ BUILD_NUMBER '"'
dr.doom
3
nie wiedział, że bash inaczej reaguje na apostrofy i podwójne cudzysłowy. Dzięki!
silgon
1
rdzenni programiści linux muszą spłonąć w piekle
goldstar
@goldstar, zauważ, że różnica między zachowaniem pojedynczego cudzysłowu i podwójnego cudzysłowu w powłoce wyprzedza Linuksa o dziesięciolecia.
sarnold
3
PSA: jeśli ciąg zawiera dane wejściowe użytkownika, jest to bardzo zły pomysł i może otworzyć cię na ataki polegające na wstrzykiwaniu kodu.
Brian McCutchon
27

Zmienne w apostrofach nie są oceniane. Użyj cudzysłowów:

ssh [email protected] "~/tools/run_pvt.pl $BUILD_NUMBER"

Powłoka rozwinie zmienne w cudzysłowach, ale nie w apostrofach. To zmieni się w żądany ciąg przed przekazaniem do sshpolecenia.

Stephen
źródło
3

(Ta odpowiedź może wydawać się niepotrzebnie skomplikowana, ale o ile wiem, jest łatwa do rozszerzenia i solidna w odniesieniu do białych znaków i znaków specjalnych).

Możesz przesyłać dane bezpośrednio przez standardowe wejście sshpolecenia i readto ze zdalnej lokalizacji.

W poniższym przykładzie

  1. tablica indeksowana jest wypełniana (dla wygody) nazwami zmiennych, których wartości chcesz pobrać po stronie zdalnej.
  2. Dla każdej z tych zmiennych dajemy ssh wiersz zakończony znakiem null, podając nazwę i wartość zmiennej.
  3. W samym shhpoleceniu przechodzimy przez te wiersze, aby zainicjować wymagane zmienne.
# 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 [email protected] '
    while read -rd '"''"' name value
    do
        export "$name"="$value"
    done

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

Wynik:

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

Jeśli ich nie potrzebujesz export, powinieneś móc użyć declarezamiast export.

Bardzo uproszczona wersja (jeśli nie potrzebujemy rozszerzalność, pojedynczą zmienną procesu itp) wyglądałby następująco:

$ ssh [email protected] 'read foo' <<< "$foo"
Alicja M.
źródło
2

Lista akceptowanych zmiennych środowiskowych na dysku SSHD domyślnie obejmuje LC_*. A zatem:

LC_MY_BUILDN="1.2.3" ssh -o "SendEnv LC_MY_BUILDN" ssh-host 'echo $LC_MY_BUILDN'
1.2.3
Alex Stragies
źródło
1

Możliwe jest również jawne przekazywanie zmiennych środowiskowych przez ssh. Wymaga konfiguracji po stronie serwera, więc nie jest to uniwersalna odpowiedź.

W moim przypadku chciałem przekazać klucz szyfrowania repozytorium kopii zapasowych do polecenia na serwerze kopii zapasowych bez przechowywania tego klucza, ale zwróć uwagę, że każda zmienna środowiskowa jest widoczna w ps! Rozwiązanie polegające na przekazaniu klucza na stdin również działałoby, ale uznałem je za zbyt kłopotliwe. W każdym razie, oto jak przekazać zmienną środowiskową przez ssh:

Na serwerze przeprowadź edycję sshd_configpliku, zazwyczaj /etc/ssh/sshd_configi dodaj AcceptEnvdyrektywę pasującą do zmiennych, które chcesz przekazać. Zobacz man sshd_config. W moim przypadku chcę przekazać zmienne do kopii zapasowej Borg, więc wybrałem:

AcceptEnv BORG_*

Teraz na kliencie użyj -o SendEnvopcji wysyłania zmiennych środowiskowych. Poniższy wiersz polecenia ustawia zmienną środowiskową, BORG_SECRETa następnie flaguje ją do wysłania do komputera klienckiego (wywoływane backup). Następnie działa printenvtam i filtruje dane wyjściowe pod kątem zmiennych BORG:

$ BORG_SECRET=magic-happens ssh -o SendEnv=BORG_SECRET backup printenv | egrep BORG
BORG_SECRET=magic-happens
TvE
źródło
Możesz "przemycić" swoje zmienne używając domyślnych ustawień po stronie serwera, zobacz moją odpowiedź . Istota jest taka, że ​​domyślna konfiguracja OpenSSHd zawiera LC_*dozwolone zmienne do wysłania, więc po prostu użyj $LC_TvE_foolub $LC_BORG_SECRETpo prostu upewnij się, że nie "kolidujesz" z wbudowaną zmienną.
Alex Stragies
0

Jak udzielono wcześniej, nie musisz ustawiać zmiennej środowiskowej na zdalnym hoście. Zamiast tego możesz po prostu wykonać meta-rozwinięcie na hoście lokalnym i przekazać wartość do hosta zdalnego.

ssh [email protected] '~/tools/run_pvt.pl $BUILD_NUMBER'

Jeśli naprawdę chcesz ustawić zmienną środowiskową na zdalnym hoście i jej używać, możesz użyć envprogramu

ssh [email protected] "env BUILD_NUMBER=$BUILD_NUMBER ~/tools/run_pvt.pl \$BUILD_NUMBER"

W tym przypadku jest to trochę przesada i uwaga

  • env BUILD_NUMBER=$BUILD_NUMBER przeprowadza ekspansję meta na lokalnym hoście
  • zdalna BUILD_NUMBERzmienna środowiskowa będzie używana przez
    zdalną powłokę
Gilles Gouaillardet
źródło
-2

Wyjdź ze zmiennej, aby uzyskać dostęp do zmiennych poza sesją ssh: ssh [email protected] "~ / tools / myScript.pl \ $ BUILD_NUMBER"

Sarah Gruneisen
źródło
2
Nie osiąga to tego, o co chodzi w pytaniu.
Patrick Trentin
2
z punktu widzenia powłoki '$FOO'jest równoważne "\$FOO". pytanie brzmiało „jak przekazać zmienną powłoki za pomocą SSH?”. Jak już stwierdził @PatrickTrentin, nie jest to poprawna odpowiedź, ponieważ BUILD_NUMBERzmienna środowiskowa nie jest ustawiana zdalnie.
Gilles Gouaillardet