Considère ceci:
$ 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"
Pourquoi l'exportation d'une variable dans une bash -c
session exécutée via ssh entraîne-t-elle cette liste de declare -x
commandes (la liste des variables actuellement exportées, pour autant que je sache)?
Exécuter la même chose sans le bash -c
ne fait pas ça:
$ ssh localhost 'export foo=bar'
terdon@localhost's password:
$
Cela ne se produit pas non plus si nous ne export
:
$ ssh localhost bash -c 'foo=bar'
terdon@localhost's password:
$
J'ai testé cela en sshing d'une machine Ubuntu à une autre (exécutant bash 4.3.11) et sur une machine Arch, en sshing comme indiqué ci-dessus (bash version 4.4.5).
Que se passe t-il ici? Pourquoi l'exportation d'une variable à l'intérieur d'un bash -c
appel produit-elle cette sortie?
export
. Zsh fait la même chose.export
, j'essaie de comprendre ce qui se passe. Je vais modifier pour préciser que cela ne se produit que lors de l'exportation.export
exécution seule? Que je n'avais pas compris.foo=bar
n'apparaît pas dans la liste.Réponses:
Lorsque vous exécutez une commande
ssh
, elle est exécutée en appelant votre$SHELL
avec l'-c
indicateur:Donc,
ssh remote_host "bash -c foo"
va réellement fonctionner:Maintenant, parce que la commande que vous exécutez (
export foo=bar
) contient des espaces et n'est pas correctement citée pour former un tout, leexport
est considéré comme la commande à exécuter et le reste est enregistré dans le tableau des paramètres de position. Cela signifie qu'ilexport
est exécuté et luifoo=bar
est transmis sous la forme$0
. Le résultat final est le même que la courseLa commande correcte serait:
la source
ssh
concatène les arguments avec des espaces et fait interpréter le shell de connexion de l'utilisateur distant, donc dans:ssh
demande au shell distant d'interpréter lacommande (en effet, si l'hôte distant est de type Unix, il déborde de la coque à distance avec
the-shell
,-c
etbash -c export foo=bar
comme arguments).La plupart des obus interpréteront cette ligne de commande en cours d' exécution de la
bash
commande avecbash
,-c
,export
etfoo=bar
comme arguments (donc courirexport
en$0
contientfoo=bar
) pendant que vous voudriez l'exécuter avecbash
,-c
etexport foo=bar
comme arguments.Pour cela, vous devez utiliser une ligne de commande comme:
(ou:
pour cela compte) donc:
la ligne de commande soit passée au shell distant. Cette ligne de commande serait interprétée par la plupart des shells que l' exécution de la
bash
commande avecbash
,-c
etexport foo=bar
comme arguments. Notez que l'utilisationne fonctionnerait pas si le shell de connexion de l'utilisateur distant était
rc
oues
par exemple où"
n'était pas un opérateur de devis spécial. Les guillemets simples sont les opérateurs de devis les plus portables (bien qu'il existe des variations sur la façon dont ils sont interprétés entre les shells, voir Comment exécuter une commande simple arbitraire sur ssh sans connaître le shell de connexion de l'utilisateur distant? Pour plus d'informations).la source