Como faço para passar uma variável do meu servidor local para um servidor remoto?

2

Estou tentando passar uma variável do meu servidor local (location1) para um servidor remoto (location2). O objetivo do código é copiar um arquivo do servidor remoto de um local predefinido. Em termos mais simples, eu quero copiar arquivos de location2 para location1 usando um caminho predefinido, onde location1 está no servidor local e location2 é um servidor remoto. Veja o segmento de código:

$location1=somewhere/on/local_server
$location2=somewhere/on/remote_server

sshpass -p "password" \
  ssh [email protected] 'su -lc "cp -r $location2 $location1";'

O erro que recebo é que tanto $ location1 quanto $ location2 estão indefinidos. Além disso, NÃO quero digitar manualmente os caminhos de localização, pois eles podem ser alterados a qualquer momento e seria difícil alterá-los no código, se feito manualmente.

    
por Alias 02.06.2014 / 16:18

6 respostas

6
As variáveis

não são expandidas entre aspas simples.

use aspas duplas e escape das aspas duplas internas:

sshpass -p "password" \
  ssh [email protected] "su -lc \"cp -r $location2 $location1\";"

ou feche as aspas simples e abra-as novamente:

sshpass -p "password" \
  ssh [email protected] 'su -lc "cp -r '$location2' '$location1'";'

o bash faz a concatenação de strings automaticamente.

nota: não testado. pode estragar-se misserably se $locationX contiver espaços ou outros caracteres estranhos.

    
por 02.06.2014 / 16:22
5

Uma variável do shell é exatamente isso: uma variável do shell. O comando ssh ou o shell iniciado por sshd no host remoto não tem como obter acesso a essa variável do shell do cliente.

As variáveis do shell

Exportado são passadas como variáveis de ambiente para os comandos executados. Portanto, se você exportou location1 , ele seria passado como uma variável de ambiente para ssh . Se você usou a diretiva de configuração SendEnv ssh (via -o ou ~/.ssh/config ou /etc/ssh/ssh_config ...), ssh tentaria enviá-la para sshd no host remoto.

No entanto, para que isso funcione, sshd precisaria ter uma diretiva de configuração AcceptEnv que permita receber essa variável. No entanto, geralmente não é o caso por motivos de segurança.

No entanto, muitas implementações padrão do ssh / sshd permitem a passagem de variáveis cujo nome começa com LC_ (para localização). Então você poderia aproveitar isso com:

LC_location1=$location1 LC_location2=$location2 ssh host 
    'su -lc '\''cp -r -- "$LC_location2" "$LC_location1"'\''

Como alternativa, você pode fazer com que o shell local expanda as variáveis na linha de comando que é passada para o shell remoto:

ssh host "su -lc 'cp -r -- $location2 $location1'"

Mas isso é o equivalente a ser executado:

eval eval "cp -r -- $location2 $location1"

Ou seja, essas variáveis não são passadas como argumentos para cp , elas são interpretadas (duas vezes) como shell (o shell de logon do usuário remoto e o código sh iniciado por su ), portanto, se $location1 é, por exemplo, /somewhere;rm -rf / , que terá consequências dramáticas.

A maneira correta seria escapar adequadamente daqueles para o shell remoto. Por causa dos dois níveis de shells, você precisa escapar as aspas simples duas vezes (aqui usando ksh93 / bash / zsh syntax):

escaped_location1=\'${location1//\'/\'\\'\'}\'
escaped_location1=${escaped_location1//\'/\'\\'\'}
escaped_location2=\'${location2//\'/\'\\'\'}\'
escaped_location2=${escaped_location2//\'/\'\\'\'}
ssh host "su -lc 'cp -r -- $escaped_location2 $escaped_location1'"

Isso pressupõe que o shell de login do usuário remoto seja parecido com Bourne.

    
por 02.06.2014 / 17:05
0

Além da resposta da lesmana: você deve citar as variáveis em seu segundo exemplo.

sshpass -p "password" \
  ssh [email protected] 'su -lc "cp -r '\\"$location2\\"' '\\"$location1\\"'";'
    
por 03.06.2014 / 20:05
0

Você também pode estar na seguinte situação: Você quer executar um programa na máquina remota que não pode ser alterado e que lê a variável $ FOO. Então você precisa de $ FOO para ser configurado na máquina remota.

Se $ FOO não contiver nenhum caracter especial de shell que você possa fazer:

ssh server FOO=$FOO the_program

Se $ FOO contiver caracteres de shell especiais, então você precisa citá-los, e é aí que ele pode ficar bastante complicado, e se $ FOO contiver \ n duplamente. Isso ainda é factível se você definir $ FOO você mesmo. Mas se $ FOO é definido por um usuário, você precisa de um programa para citá-lo para você. Uma solução é (ab) usando o GNU Parallel:

export FOO
parallel -N0 -S server --env FOO the_program ::: ""

O GNU Parallel sabe como transferir variáveis com todos os tipos de caracteres especiais. Por exemplo:

FOO='* < " > $ ! # @ ) ( ] [ } { | & % \ ''here is a quoted newline
more of FOO'"'"'s content'
export FOO
parallel -N0 -S localhost --env FOO echo '"$FOO"' ::: ""
    
por 24.06.2014 / 09:36
0

Veja este script que escrevi para atualizar nosso serviço.

PROJ=$2 será passado para o env de execução remota.

function update-env () {
    env=$1
    proj=$2

    # script for update test env
    ssh -A root@$2.$1.test.com PROJ=$2 'bash -s' <<'ENDSSH'
        # commands to run on remote host
        su gmuser
        cd /srv/apps/$PROJ
        /usr/bin/git pull
        exit
        supervisorctl restart $PROJ
    ENDSSH
}
    
por 16.11.2015 / 07:34
-1

apenas escreva a variável ou os dados necessários em um arquivo local e, em seguida, no script, execute um comando scp para enviar o arquivo ao servidor remoto. no servidor remoto, tenha um script que verifique periodicamente (via cron) o arquivo, leia seu conteúdo e faça o que quiser.

    
por 19.04.2015 / 15:49