Considera esto:
$ 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"
¿Por qué la exportación de una variable dentro de un bash -c
plazo de sesión a través de ssh resultado en esa lista de declare -x
comandos (la lista de variables actualmente exportados, por lo que yo puedo decir)?
Ejecutar lo mismo sin el bash -c
no hace eso:
$ ssh localhost 'export foo=bar'
terdon@localhost's password:
$
Tampoco sucede si no lo hacemos export
:
$ ssh localhost bash -c 'foo=bar'
terdon@localhost's password:
$
Probé esto enviando mensajes de una máquina Ubuntu a otra (ambos ejecutando bash 4.3.11) y en una máquina Arch, enviando mensajes a sí mismo como se muestra arriba (versión bash 4.4.5).
¿Que está pasando aqui? ¿Por qué exportar una variable dentro de una bash -c
llamada produce esta salida?
export
. Zsh hace lo mismo.export
, estoy tratando de entender qué está pasando. Lo editaré para aclarar que esto solo ocurre al exportar.export
correr solo? Eso no lo había entendido.foo=bar
no aparece en la lista.Respuestas:
Cuando ejecuta un comando
ssh
, se ejecuta llamando a$SHELL
con la-c
bandera:Entonces, en
ssh remote_host "bash -c foo"
realidad se ejecutará:Ahora, debido a que el comando que está ejecutando (
export foo=bar
) contiene espacios y no se cita correctamente para formar un todo,export
se toma como el comando a ejecutar y el resto se guarda en la matriz de parámetros posicionales. Esto significa queexport
se ejecuta yfoo=bar
se le pasa como$0
. El resultado final es el mismo que correrEl comando correcto sería:
fuente
ssh
concatena los argumentos con espacios y hace que el shell de inicio de sesión del usuario remoto lo interprete, así que en:ssh
está pidiendo al shell remoto que interprete elde comandos (en efecto, si el host remoto es similar a Unix, pondrá en funcionamiento el shell remoto con
the-shell
,-c
ybash -c export foo=bar
como argumentos).La mayoría de las conchas interpretarán que la línea de comandos como ejecutar el
bash
comando conbash
,-c
,export
yfoo=bar
como argumentos (para correrexport
mientras que$0
contienefoo=bar
), mientras que le desea que se ejecute conbash
,-c
yexport foo=bar
como argumentos.Para eso, necesitaría usar una línea de comando como:
(o:
para eso importa) así que:
la línea de comando se pasa al shell remoto. Esa línea de comandos sería interpretado por la mayoría de conchas como ejecutar el
bash
comando conbash
,-c
yexport foo=bar
como argumentos. Tenga en cuenta que usandono funcionaría si el shell de inicio de sesión del usuario remoto fuera
rc
oes
por ejemplo,"
no fuera un operador de cotización especial. Las comillas simples son los operadores de comillas más portátiles (aunque hay alguna variación en cómo se interpretan entre shells, consulte ¿Cómo ejecutar un comando simple arbitrario sobre ssh sin conocer el shell de inicio de sesión del usuario remoto? Para obtener más información).fuente