Rozważ to:
$ 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"
Dlaczego eksportowanie zmiennej w ramach bash -c
sesji uruchamianej przez ssh powoduje, że ta lista declare -x
poleceń (lista aktualnie eksportowanych zmiennych, o ile mi wiadomo)?
Uruchamianie tego samego bez tego bash -c
nie robi:
$ ssh localhost 'export foo=bar'
terdon@localhost's password:
$
Nie stanie się tak, jeśli nie export
:
$ ssh localhost bash -c 'foo=bar'
terdon@localhost's password:
$
Przetestowałem to przez sshing z jednego komputera Ubuntu na inny (oba z uruchomionym bash 4.3.11) i na komputerze Arch, sshing do siebie, jak pokazano powyżej (wersja bash 4.4.5).
Co tu się dzieje? Dlaczego eksportowanie zmiennej wewnątrz bash -c
wywołania daje taki wynik?
export
. Zsh robi to samo.export
, próbuję zrozumieć, co się dzieje. Przeredaguję, aby wyjaśnić, że dzieje się to tylko podczas eksportowania.export
samego uruchomienia? Tego nie zrozumiałem.foo=bar
nie ma go na liście.Odpowiedzi:
Po uruchomieniu polecenia
ssh
jest ono uruchamiane przez wywołanie flagi$SHELL
z-c
flagą:Tak więc
ssh remote_host "bash -c foo"
będzie działać:Teraz, ponieważ polecenie, które uruchamiasz (
export foo=bar
) zawiera spacje i nie jest poprawnie cytowane w celu utworzenia całości,export
jest traktowane jako polecenie do uruchomienia, a reszta jest zapisywana w tablicy parametrów pozycyjnych. Oznacza to, żeexport
jest uruchamiany ifoo=bar
przekazywany do niego jako$0
. Ostateczny wynik jest taki sam jak bieganiePrawidłowe polecenie to:
źródło
ssh
łączy argumenty ze spacjami i ma powłokę logowania zdalnego użytkownika, która je interpretuje, więc w:ssh
prosi zdalną powłokę o interpretacjępolecenie (w praktyce, o ile pilot gospodarz jest typu Unix, będzie uruchamiać zdalnym powłoki z
the-shell
,-c
ibash -c export foo=bar
jako argumenty).Większość muszle zinterpretuje to jako wiersz polecenia, uruchamiając
bash
komendębash
,-c
,export
afoo=bar
jako argumenty (tak prowadzonyexport
, gdy$0
zawierafoo=bar
), podczas gdy tylko chcesz go uruchomić gobash
,-c
aexport foo=bar
jako argumenty.W tym celu należy użyć wiersza polecenia, takiego jak:
(lub:
w tym przypadku), więc:
wiersz polecenia należy przekazać do zdalnej powłoki. Że wiersz poleceń będzie interpretowane przez większość muszli jak uruchomienie
bash
polecenia zbash
,-c
aexport foo=bar
jako argumenty. Zauważ, że za pomocąnie działałby, gdyby powłoka logowania zdalnego użytkownika była
rc
lubes
na przykład, gdy"
nie jest specjalnym operatorem cytowania. Pojedyncze cudzysłowy to najbardziej przenośne operatory cytowania (chociaż istnieją pewne różnice w ich interpretacji między powłokami, zobacz Jak wykonać dowolne proste polecenie za pomocą ssh bez znajomości powłoki logowania użytkownika zdalnego? Więcej na ten temat).źródło