Considere isto:
$ 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 que exportar uma variável dentro de uma bash -c
sessão executada via ssh resulta nessa lista de declare -x
comandos (a lista de variáveis atualmente exportadas, até onde eu sei)?
Executar a mesma coisa sem o bash -c
não faz isso:
$ ssh localhost 'export foo=bar'
terdon@localhost's password:
$
Nem acontece se não o fizermos export
:
$ ssh localhost bash -c 'foo=bar'
terdon@localhost's password:
$
Eu testei isso sshing de uma máquina Ubuntu para outra (ambas executando o bash 4.3.11) e em uma máquina Arch, sshing para si mesma, como mostrado acima (versão do bash 4.4.5).
O que está acontecendo aqui? Por que exportar uma variável dentro de uma bash -c
chamada produz essa saída?
export
. Zsh faz a mesma coisa.export
estou tentando entender o que está acontecendo. Vou editar para esclarecer que isso só acontece na exportação.export
correr sozinho? Isso eu não tinha entendido.foo=bar
não aparece na lista.Respostas:
Quando você executa um comando
ssh
, ele é executado chamando seu$SHELL
com o-c
sinalizador:Então,
ssh remote_host "bash -c foo"
na verdade , será executado:Agora, como o comando que você está executando (
export foo=bar
) contém espaços e não é adequadamente citado para formar um todo, eleexport
é tomado como o comando a ser executado e o restante é salvo na matriz de parâmetros posicionais. Isso significa queexport
é executado efoo=bar
passado para ele como$0
. O resultado final é o mesmo que correrO comando correto seria:
fonte
ssh
concatena os argumentos com espaços e faz com que o shell de login do usuário remoto o interprete, em:ssh
está pedindo ao shell remoto para interpretar ode comando (na verdade, se o host remoto é Unix-like, ele irá executar o shell remoto com
the-shell
,-c
ebash -c export foo=bar
como argumentos).A maioria das conchas irá interpretar essa linha de comando como executar o
bash
comando combash
,-c
,export
efoo=bar
como argumentos (para executarexport
enquanto$0
contémfoo=bar
), enquanto você ia querer que ele seja executado combash
,-c
eexport foo=bar
como argumentos.Para isso, você precisará usar uma linha de comando como:
(ou:
para esse assunto) de modo que:
linha de comando seja passada para o shell remoto. Essa linha de comando seria interpretado pela maioria das conchas como executar o
bash
comando combash
,-c
eexport foo=bar
como argumentos. Observe que usarnão funcionaria se o shell de login do usuário remoto estivesse
rc
ou,es
por exemplo, onde"
não fosse um operador de cotação especial. As aspas simples são os operadores de cotação mais portáteis (embora exista alguma variação em como eles são interpretados entre shells, consulte Como executar um comando simples e arbitrário sobre o ssh sem conhecer o shell de login do usuário remoto? Para saber mais sobre isso).fonte