Bedenken Sie:
$ 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"
Warum führt das Exportieren einer Variablen innerhalb einer bash -c
Sitzung, die über ssh ausgeführt wird, zu dieser Liste von declare -x
Befehlen (die Liste der derzeit exportierten Variablen, soweit ich das beurteilen kann)?
Dasselbe ohne das bash -c
auszuführen, macht das nicht:
$ ssh localhost 'export foo=bar'
terdon@localhost's password:
$
Es passiert auch nicht, wenn wir nicht export
:
$ ssh localhost bash -c 'foo=bar'
terdon@localhost's password:
$
Ich habe dies getestet, indem ich von einem Ubuntu-Rechner auf einen anderen (beide mit Bash 4.3.11) und auf einen Arch-Rechner sshing, wie oben gezeigt (Bash-Version 4.4.5).
Was ist denn hier los? Warum erzeugt das Exportieren einer Variablen innerhalb eines bash -c
Aufrufs diese Ausgabe?
export
. Zsh macht das Gleiche.export
, ich versuche zu verstehen, was passiert. Ich bearbeite, um zu verdeutlichen, dass dies nur beim Export geschieht.export
Run alone? Das hatte ich nicht verstanden.foo=bar
nicht in der Liste angezeigt wird.Antworten:
Wenn Sie einen Befehl ausführen
ssh
, wird er ausgeführt, indem Sie$SHELL
mit dem-c
Flag your aufrufen :Also,
ssh remote_host "bash -c foo"
wird tatsächlich ausgeführt:Da der Befehl, den Sie ausführen (
export foo=bar
), Leerzeichen enthält und nicht in Anführungszeichen steht, um ein Ganzes zu bilden,export
wird der Befehl als auszuführender Befehl verwendet und der Rest wird im Array mit den Positionsparametern gespeichert. Das heißt, esexport
wird ausgeführt undfoo=bar
als übergeben$0
. Das Endergebnis ist dasselbe wie beim LaufenDer richtige Befehl wäre:
quelle
ssh
Verkettet die Argumente mit Leerzeichen und lässt sie von der Anmeldeshell des Remotebenutzers interpretieren.ssh
fragt die Remote-Shell nach der Interpretation desBefehl (in der Tat , wenn die Remote - Host ist Unix-like, wird es die Remote - Shell mit laufen
the-shell
,-c
undbash -c export foo=bar
als Argument).Die meisten Schalen werden diese Befehlszeile interpretieren als den
bash
Laufbefehl mitbash
,-c
,export
undfoo=bar
als Argument (so liefen ,export
während$0
enthaltenfoo=bar
) , während Sie es wollen , dass es würden laufen mitbash
,-c
undexport foo=bar
als Argument.Dafür müssten Sie eine Befehlszeile wie folgt verwenden:
(oder:
für das zählt) so das:
Kommandozeile an die Remote-Shell übergeben werden. Das Befehlszeile würde den von den meisten Schalen interpretiert wird als Lauf
bash
mit dem Befehlbash
,-c
undexport foo=bar
als Argument. Beachten Sie, dass mitwürde nicht funktionieren, wenn die Login-Shell des entfernten Benutzers wäre
rc
oder wennes
zum Beispiel"
kein spezieller Anführungszeichenoperator vorhanden ist. Einfache Anführungszeichen sind die portabelsten Operatoren für Anführungszeichen (obwohl es einige Unterschiede in der Interpretation zwischen den Shells gibt, finden Sie weitere Informationen dazu unter So führen Sie einen beliebigen einfachen Befehl über ssh aus, ohne die Anmeldeshell des Remotebenutzers zu kennen ).quelle