Vários comandos durante um SSH dentro de uma sessão SSH


10

Eu tenho uma máquina local que deveria fazer uma sessão SSH em uma mastermáquina remota e, em seguida, outra sessão SSH interna de masterpara cada um dos remotos slaves, e depois executar 2 comandos, ou seja, para excluir um diretório específico e recriá-lo.

Observe que a máquina local possui SSH sem senha para o mestre e o mestre tem SSH sem senha para os escravos. Também todos os nomes de host são conhecidos nas .ssh/configmáquinas locais / master e os nomes de host dos escravos estão slaves.txtlocalmente e eu os leio a partir daí.

Então, o que eu faço e funciona é o seguinte:

username="ubuntu"
masterHostname="myMaster"
while read line
do

    #Remove previous folders and create new ones.
    ssh -n $username@$masterHostname "ssh -t -t $username@$line "rm -rf Input Output Partition""
    ssh -n $username@$masterHostname "ssh -t -t $username@$line "mkdir -p EC2_WORKSPACE/$project Input Output Partition""


    #Update changed files...
    ssh -n $username@$masterHostname "ssh -t -t $username@$line "rsync --delete -avzh /EC2_NFS/$project/* EC2_WORKSPACE/$project""

done < slaves.txt 

Este cluster está no Amazon EC2 e notei que existem 6 sessões SSH criadas a cada iteração, o que induz um atraso significativo. Gostaria de combinar esses 3 comandos em 1 para obter menos conexões SSH. Então, eu tentei combinar os 2 primeiros comandos em

ssh -n $username@$masterHostname "ssh -t -t $username@$line "rm -rf Input Output Partition && mkdir -p EC2_WORKSPACE/$project Input Output Partition""

Mas não funciona como esperado. Parece executar o primeiro ( rm -rf Input Output Partition) e depois sai da sessão e continua. O que eu posso fazer?


3
Em vez de tal indireção no comando, você pode usar a -Jopção que definiria seu host de salto.
Hauleth

Respostas:


15

Considere que este &&é um operador lógico. Isso não significa "também execute este comando", significa "execute este comando se o outro tiver êxito".

Isso significa que se o rmcomando falhar (o que acontecerá se algum dos três diretórios não existir), mkdirele não será executado. Isso não soa como o comportamento que você deseja; se os diretórios não existirem, provavelmente será bom criá-los.

Usar ;

O ponto ;e vírgula é usado para separar comandos. Os comandos são executados seqüencialmente, aguardando um antes de continuar no próximo, mas seu sucesso ou falha não tem impacto um no outro.

Fugir das citações internas

As aspas dentro de outras aspas devem ser escapadas; caso contrário, você estará criando um ponto final e um ponto inicial adicionais. Seu comando:

ssh -n $username@$masterHostname "ssh -t -t $username@$line "rm -rf Input Output Partition && mkdir -p EC2_WORKSPACE/$project Input Output Partition""

Torna-se:

ssh -n $username@$masterHostname "ssh -t -t $username@$line \"rm -rf Input Output Partition && mkdir -p EC2_WORKSPACE/$project Input OutputPartition\""

Seu comando atual, devido à falta de aspas escapadas, deve estar executando:

ssh -n $username@$masterHostname "ssh -t -t $username@$line "rm -rf Input Output Partition

se isso tiver êxito:

mkdir -p EC2_WORKSPACE/$project Input Output Partition"" # runs on your local machine

Você notará que o realce da sintaxe mostra todo o comando em vermelho aqui, o que significa que todo o comando é a string que está sendo passada para o ssh. Verifique sua máquina local; você pode ter os diretórios Input Outpute Partitiononde estava executando isso.


Eu entendo seus pontos de vista. Uma parte pela qual fiquei confuso foi o ponto-e-vírgula, pois pensei que executaria mais de um comando ao mesmo tempo, razão pela qual não o usei.
mgus 26/07

O ponto-e-vírgula não fará com que os comandos sejam executados ao mesmo tempo, veja aqui como uma referência para a execução de comandos. Os &comandos de causas são executados em segundo plano, o que significa que eles não serão esperados para concluir antes de passar para o próximo.
Centimane 26/07

10

Você sempre pode definir na sua caixa de salto Multiplexação no OpenSSH

Multiplexagem é a capacidade de enviar mais de um sinal por uma única linha ou conexão. Com a multiplexação, o OpenSSH pode reutilizar uma conexão TCP existente para várias sessões SSH simultâneas, em vez de criar uma nova a cada vez.

Uma vantagem da multiplexação SSH é que a sobrecarga da criação de novas conexões TCP é eliminada. O número geral de conexões que uma máquina pode aceitar é um recurso finito e o limite é mais perceptível em algumas máquinas do que em outras e varia muito, dependendo da carga e do uso. Também há um atraso significativo ao abrir uma nova conexão. As atividades que abrem novas conexões repetidamente podem ser significativamente aceleradas usando a multiplexação.

Para que faça em /etc/ssh/ssh_config:

ControlMaster auto
ControlPath ~/.ssh/controlmasters/ssh_mux_%h_%p_%r
ControlPersist 30m

Dessa maneira, todas as conexões consecutivas feitas no mesmo servidor nos 30 minutos seguintes serão feitas reutilizando a conexão ssh anterior.

Você também pode defini-lo para uma máquina ou grupo de máquinas. Retirado do link fornecido.

Host machine1
    HostName machine1.example.org
    ControlPath ~/.ssh/controlmasters/%r@%h:%p
    ControlMaster auto
    ControlPersist 10m

Isso é interessante! Existe uma maneira de ativá-lo e desativá-lo explicitamente para uma determinada conexão? Parece que o exagero altera drasticamente todas as conexões SSH para este caso de uso. Pode ser usado de maneira mais precisa? Para iniciar a multiplexação apenas de uma certa conexão?
Centimane

@Centimane sim, atualizei a resposta
Rui F Ribeiro

1
Eu sugeriria colocar o soquete na casa do usuário, em vez de um mundo gravável /tmp/.
heemayl

@heemayl Bom ponto. Vou editá-lo quando estiver em um computador.
Rui F Ribeiro

@RuiFRibeiro Também parece, de acordo com man ssh, ControlPath, ControlMastere ControlPersistsão opções válidas para passar um sshcomando usando -o. Pode ser um caso de uso ainda mais preciso, configure a multiplexação no primeiro sshdo script e recicle-o para os outros, mas evite a penalidade de desempenho. Eu me pergunto o que o valor de referência de multiplexação VS não para 3 conexões SSH, dado que "Há também um atraso significativo quando se abre uma nova conexão"
Centimane

4

Você pode colocar todos os seus comandos em um script separado no servidor "mestre".

Script mestre

#!/bin/bash
rm -rf "Input Output Partition"
mkdir -p "EC2_WORKSPACE/$project Input Output Partition"

Em seguida, no seu script ssh, chame-o assim: Script SSH

username="ubuntu"
masterHostname="myMaster"
while read line
do
ssh -n $username@$masterHostname "ssh -t -t $username@$line < /path/to/masterscript.sh"
ssh -n $username@$masterHostname "ssh -t -t $username@$line "rsync --delete -avzh /EC2_NFS/$project/* EC2_WORKSPACE/$project""
done < slaves.txt 

OU se todos os arquivos tiverem que estar na máquina inicial, você poderá fazer algo assim:

script1

script2="/path/to/script2"
username="ubuntu"
while read line; do
cat $script2 | ssh -t -t $username@line
done < slaves.txt

script2

#!/bin/bash
rm -rf "Input Output Partition"
mkdir -p "EC2_WORKSPACE/$project Input Output Partition"
rsync --delete -avzh "/EC2_NFS/$project/* EC2_WORKSPACE/$project"

script ssh

script1="/path/to/script1"
username="ubuntu"
masterHostname="myMaster"
cat $script1 | ssh -n $username@$masterHostname

1

Há algum tempo, tive a oportunidade de usar soquetes de controle como as outras respostas recomendam (essa resposta é essencialmente uma combinação do uso de soquetes de controle como esta resposta e scripts como essa resposta ).

O caso de uso foi um hack: authorized_keyso usuário de destino era substituído periodicamente por uma tarefa agendada e eu queria testar rapidamente as coisas sem passar pela burocracia necessária para adicionar algo a esse arquivo. Então, eu configurei um loop while que adicionou a chave ao arquivo, conforme necessário, execute meu teste e cancele o loop. No entanto, haveria uma pequena janela onde a tarefa agendada sobrescreveria o arquivo e meu loop ainda estaria em sleepexecução. Portanto, configurar um soquete de controle no início deixaria meu script SSH posteriormente sem problemas:

#! /bin/bash -xe
. "${CONFIG_DIR}/scripts/setup-ssh.sh"

# Build and test
export TEST_LABEL="${_started_by}-${BUILD_TAG%-BUILD*}"
#...
xargs --arg-file test-list \
    --no-run-if-empty \
    --process-slot-var=NUM \
    --max-procs=${#SERVERS[@]} \
    --max-args="${BATCH_SIZE:-20}" \
    "${CONFIG_DIR}/scripts/run-test.sh"

Onde setup-ssh.shfica:

export SSH_CONFIG="${CONFIG_DIR}/scripts/.ssh-config"
mapfile -t SERVERS < "${CONFIG_DIR}/scripts/hosts"

for SERVER in "${SERVERS[@]}"
do
    while ! ssh -F "${SSH_CONFIG}" "${SERVER}" -fnN; do sleep 1; done
    scp -F "${SSH_CONFIG}" "${CONFIG_DIR}/scripts/ssh-script.sh" "${SERVER}":"${TEST_LABEL}.sh"
done

E .ssh-config:

Host test-*
  User test
  StrictHostKeyChecking no
  ControlMaster auto
  ControlPath /tmp/ssh-%h-%p-%r

E run-test.sh:

mapfile -t TEST_SERVERS < "${CONFIG_DIR}/scripts/hosts"
ssh -F "${SSH_CONFIG}" "${TEST_SERVERS[$NUM]}" "./${TEST_LABEL}.sh"

A sequência é assim:

  • O script principal (mostrado primeiro) fontes setup-ssh.sh.
  • setup-ssh.shocupado-loops os servidores até que todos eles tenham uma configuração de soquete de controle. O hostsarquivo simplesmente lista os nomes de host do servidor, um por linha.
  • Como a configuração que especifica o soquete de controle é apenas ${CONFIG_DIR}/scripts/.ssh-config, a menos que eu especifique esse arquivo -F, as conexões SSH não o usarão. Portanto, isso me permite usar o soquete de controle somente onde eu precisar deles usando a Fopção
  • O script de instalação também copia o script de execução de teste para os servidores. O próprio script de execução contém vários comandos e, como eu copiei o script de execução, não preciso me preocupar com uma camada adicional de citação para SSH (e a sobrecarga cognitiva adicional para descobrir o que é expandido quando).
  • Em seguida, o script principal usa xargspara distribuir a carga de trabalho pelos servidores, iniciando novos trabalhos assim que os em execução terminam.
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.