Passando variáveis ​​no comando ssh remoto

99

Eu quero ser capaz de executar um comando da minha máquina usando ssh e passar pela variável de ambiente $BUILD_NUMBER

Aqui está o que estou tentando:

ssh pvt@192.168.1.133 '~/tools/myScript.pl $BUILD_NUMBER'

$BUILD_NUMBER é definido na máquina que faz a chamada ssh e, como a variável não existe no host remoto, ela não é selecionada.

Como passo o valor de $BUILD_NUMBER?

Fergal
fonte
1
não relacionado a Hudson, removeu a etiqueta. (Hudson acaba de criar a variável)
Peter Schuetze

Respostas:

188

Se você usar

ssh pvt@192.168.1.133 "~/tools/run_pvt.pl $BUILD_NUMBER"

ao invés de

ssh pvt@192.168.1.133 '~/tools/run_pvt.pl $BUILD_NUMBER'

seu shell irá interpolar o $BUILD_NUMBERantes de enviar a string de comando para o host remoto.

Sarnold
fonte
8
Se alguém DEVE usar aspas simples para que o comando incluído nas aspas não seja avaliado localmente, deve usar "'$ VARIABLE'". Exemplo: ssh [email protected] '~ / tools / run_pvt.pl "' $ BUILD_NUMBER '"'
dr.doom
3
não sabia que o bash reage de maneira diferente com aspas simples e aspas duplas. Obrigado!
silgon
1
os desenvolvedores do núcleo do Linux devem queimar no inferno
goldstar
@goldstar, observe que a diferença entre aspas simples e aspas duplas no shell é anterior ao Linux em décadas.
sarnold
3
PSA: se sua string contém entrada do usuário, isso é uma ideia muito ruim e pode deixá-lo vulnerável a ataques de injeção de código.
Brian McCutchon de
27

Variáveis ​​em aspas simples não são avaliadas. Use aspas duplas:

ssh pvt@192.168.1.133 "~/tools/run_pvt.pl $BUILD_NUMBER"

O shell irá expandir as variáveis ​​entre aspas duplas, mas não entre aspas simples. Isso mudará para a string desejada antes de ser passado para o sshcomando.

Stephen
fonte
2

(Esta resposta pode parecer desnecessariamente complicada, mas é facilmente extensível e robusta em relação a espaços em branco e caracteres especiais, pelo que eu sei.)

Você pode alimentar dados diretamente por meio da entrada padrão do sshcomando e readde um local remoto.

No exemplo a seguir,

  1. uma matriz indexada é preenchida (por conveniência) com os nomes das variáveis ​​cujos valores você deseja recuperar no lado remoto.
  2. Para cada uma dessas variáveis, damos a sshuma linha terminada em nulo fornecendo o nome e o valor da variável.
  3. No shhpróprio comando, percorremos essas linhas para inicializar as variáveis ​​necessárias.
# Initialize examples of variables.
# The first one even contains whitespace and a newline.
readonly FOO=$'apjlljs ailsi \n ajlls\t éjij'
readonly BAR=ygnàgyààynygbjrbjrb

# Make a list of what you want to pass through SSH.
# (The “unset” is just in case someone exported
# an associative array with this name.)
unset -v VAR_NAMES
readonly VAR_NAMES=(
    FOO
    BAR
)

for name in "${VAR_NAMES[@]}"
do
    printf '%s %s\0' "$name" "${!name}"
done | ssh user@somehost.com '
    while read -rd '"''"' name value
    do
        export "$name"="$value"
    done

    # Check
    printf "FOO = [%q]; BAR = [%q]\n" "$FOO" "$BAR"
'

Resultado:

FOO = [$'apjlljs ailsi \n ajlls\t éjij']; BAR = [ygnàgyààynygbjrbjrb]

Se você não precisar exportdeles, poderá usar em declarevez de export.

Uma versão realmente simplificada (se você não precisa da extensibilidade, tem uma única variável para processar, etc.) seria semelhante a:

$ ssh user@somehost.com 'read foo' <<< "$foo"
Alice M.
fonte
2

A lista de variáveis ​​de ambiente aceitas no SSHD por padrão inclui LC_*. Portanto:

LC_MY_BUILDN="1.2.3" ssh -o "SendEnv LC_MY_BUILDN" ssh-host 'echo $LC_MY_BUILDN'
1.2.3
Alex Stragies
fonte
0

Conforme respondido anteriormente, você não precisa definir a variável de ambiente no host remoto. Em vez disso, você pode simplesmente fazer a meta-expansão no host local e passar o valor para o host remoto.

ssh pvt@192.168.1.133 '~/tools/run_pvt.pl $BUILD_NUMBER'

Se você realmente deseja definir a variável de ambiente no host remoto e usá-la, você pode usar o envprograma

ssh pvt@192.168.1.133 "env BUILD_NUMBER=$BUILD_NUMBER ~/tools/run_pvt.pl \$BUILD_NUMBER"

Neste caso, isso é um pouco exagerado, e observe

  • env BUILD_NUMBER=$BUILD_NUMBER faz a metaexpansão no host local
  • a BUILD_NUMBERvariável de ambiente remoto será usada pelo
    shell remoto
Gilles Gouaillardet
fonte
0

Também é possível passar variáveis ​​de ambiente explicitamente por meio de ssh. Requer alguma configuração do lado do servidor, portanto, esta não é uma resposta universal.

No meu caso, eu queria passar uma chave de criptografia do repositório de backup para um comando no servidor de armazenamento de backup sem ter essa chave armazenada lá, mas observe que qualquer variável de ambiente é visível em ps! A solução de passar a chave para stdin também funcionaria, mas eu a achei muito complicada. Em qualquer caso, veja como passar uma variável de ambiente por meio de ssh:

No servidor, edite o sshd_configarquivo, normalmente /etc/ssh/sshd_confige adicione uma AcceptEnvdiretiva que corresponda às variáveis ​​que você deseja passar. Veja man sshd_config. No meu caso, quero passar variáveis ​​para o backup do borg, então escolhi:

AcceptEnv BORG_*

Agora, no cliente, use a -o SendEnvopção de enviar variáveis ​​de ambiente. A linha de comando a seguir define a variável de ambiente BORG_SECRETe a sinaliza para ser enviada à máquina cliente (chamada backup). Em seguida, ele executa printenvlá e filtra a saída para variáveis ​​BORG:

$ BORG_SECRET=magic-happens ssh -o SendEnv=BORG_SECRET backup printenv | egrep BORG
BORG_SECRET=magic-happens
TvE
fonte
Você pode "contrabandear" suas variáveis ​​usando as configurações padrão do servidor, veja minha resposta . A essência é que a configuração padrão do OpenSSHd inclui LC_*como Variáveis ​​permitidas para enviar, então apenas use $LC_TvE_foo, ou $LC_BORG_SECRET, apenas certifique-se de não "colidir" com uma variável embutida.
Alex Stragies
-2

Escape a variável para acessar variáveis ​​fora da sessão ssh: ssh [email protected] "~ / tools / myScript.pl \ $ BUILD_NUMBER"

Sarah Gruneisen
fonte
2
Isso não atinge o que a pergunta está pedindo.
Patrick Trentin
2
do ponto de vista da concha, '$FOO'é equivalente a "\$FOO". a questão era "como passar uma variável shell com SSH?". Como já foi dito por @PatrickTrentin esta não é uma resposta correta porque BUILD_NUMBERa variável de ambiente não é configurada remotamente.
Gilles Gouaillardet