Comandi multipli durante un SSH all'interno di una sessione SSH


10

Ho una macchina locale che dovrebbe fare una sessione SSH su una mastermacchina remota e poi un'altra sessione SSH interna da mastera ciascuno di alcuni telecomandi slaves, e quindi eseguire 2 comandi cioè per eliminare una directory specifica e ricrearla.

Si noti che il computer locale ha SSH senza password per il master e il master ha SSH senza password per gli slave. Inoltre, tutti i nomi host sono noti nelle .ssh/configmacchine locali / master e i nomi host degli schiavi sono slaves.txtlocalmente e li leggo da lì.

Quindi quello che faccio e lavoro è questo:

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 

Questo cluster è su Amazon EC2 e ho notato che ci sono 6 sessioni SSH create ad ogni iterazione che inducono un ritardo significativo. Vorrei combinare questi 3 comandi in 1 per ottenere meno connessioni SSH. Quindi ho provato a combinare i primi 2 comandi in

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

Ma non funziona come previsto. Sembra che esegua il primo ( rm -rf Input Output Partition), quindi esce dalla sessione e continua. Cosa posso fare?


3
Invece di tale indiretto al comando puoi usare l' -Jopzione che definirebbe il tuo host di salto.
Hauleth,

Risposte:


15

Considera che &&è un operatore logico. Lo fa non media "eseguito anche questo comando" significa "eseguire questo comando se l'altro è riuscito".

Ciò significa che se il rmcomando fallisce (cosa che succederà se una delle tre directory non esiste), allora mkdirnon verrà eseguita. Questo non suona come il comportamento desiderato; se le directory non esistono, probabilmente va bene crearle.

Uso ;

Il punto ;e virgola viene utilizzato per separare i comandi. I comandi vengono eseguiti in sequenza, in attesa di ciascuno prima di continuare con il successivo, ma il loro successo o fallimento non hanno alcun impatto reciproco.

Sfuggire alle virgolette interne

Le citazioni all'interno di altre virgolette dovrebbero essere evitate, altrimenti stai creando un punto finale e un punto iniziale extra. Il tuo comando:

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

diventa:

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

Il tuo comando corrente, a causa della mancanza di virgolette di escape dovrebbe essere in esecuzione:

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

se ciò ha esito positivo:

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

Noterai che l'evidenziazione della sintassi mostra l'intero comando in rosso qui, il che significa che l'intero comando è la stringa che viene passata a ssh. Controlla la tua macchina locale; potresti avere le directory Input Outpute Partitiondove stavi eseguendo questo.


Capisco i tuoi punti. Una parte di cui ero confuso era il punto e virgola, poiché pensavo che avrebbe eseguito più di 1 comandi contemporaneamente, motivo per cui non l'ho usato.
MGUS

Il punto e virgola non farà in modo che i comandi vengano eseguiti contemporaneamente, vedere qui come riferimento per l'esecuzione dei comandi. I &comandi vengono eseguiti in background, il che significa che non verranno attesi per finire prima di passare al successivo.
Centimane,

10

Puoi sempre definire nel tuo jumpbox il multiplexing in OpenSSH

Il multiplexing è la capacità di inviare più di un segnale su una singola linea o connessione. Con il multiplexing, OpenSSH può riutilizzare una connessione TCP esistente per più sessioni SSH simultanee anziché crearne una nuova ogni volta.

Un vantaggio con il multiplexing SSH è l'eliminazione del sovraccarico di creazione di nuove connessioni TCP. Il numero complessivo di connessioni che una macchina può accettare è una risorsa limitata e il limite è più evidente su alcune macchine che su altre e varia notevolmente a seconda del carico e dell'utilizzo. C'è anche un ritardo significativo all'apertura di una nuova connessione. Le attività che aprono ripetutamente nuove connessioni possono essere notevolmente accelerate utilizzando il multiplexing.

Per questo fare in /etc/ssh/ssh_config:

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

In questo modo, tutte le connessioni consecutive effettuate allo stesso server nei successivi 30 minuti verranno riutilizzate la precedente connessione ssh.

Puoi anche definirlo per una macchina o un gruppo di macchine. Tratto dal link fornito.

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

Interessante! C'è un modo per accenderlo e spegnerlo esplicitamente per una determinata connessione? Sembra eccessivo cambiare così drasticamente tutte le connessioni SSH per questo caso d'uso. Può essere usato in modo più preciso? Per iniziare il multiplexing solo una determinata connessione?
Centimane,

@Centimane sì, aggiornata la risposta
Rui F Ribeiro,

1
Vorrei suggerire di mettere la presa nella casa dell'utente piuttosto che un mondo leggibile /tmp/.
heemayl

@heemayl Ottimo punto. Lo modificherò quando in un computer.
Rui F Ribeiro,

@RuiFRibeiro appare anche come, secondo man ssh, ControlPath, ControlMastere ControlPersistsono opzioni valide per passare un sshcomando utilizzando -o. Potrebbe essere un caso d'uso ancora più preciso, impostare il multiplexing nel primo sshscript e riciclarlo per gli altri, ma altrimenti evitare la penalità prestazionale. Mi chiedo quale sia il punto di riferimento del multiplexing VS non per 3 connessioni SSH, dato che "C'è anche un ritardo significativo all'apertura di una nuova connessione"
Centimane,

4

Puoi inserire tutti i tuoi comandi in uno script separato sul tuo server "master".

Master Script

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

Quindi nel tuo script ssh chiamalo così: 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 

OPPURE se tutti i file devono trovarsi sul computer iniziale, è possibile fare qualcosa del genere:

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

Qualche tempo fa, ho avuto occasione di usare socket di controllo come le altre risposte raccomandano (questa risposta è essenzialmente una combinazione dell'uso di socket di controllo come questa risposta e di script come questa risposta ).

Il caso d'uso era un hack: authorized_keysl'utente target veniva sovrascritto periodicamente da un'attività pianificata e volevo testare rapidamente le cose senza dover ricorrere alla burocrazia necessaria per aggiungere qualcosa a quel file. Quindi ho impostato un ciclo while che ha aggiunto la chiave a quel file in base alle esigenze, ho eseguito il mio test e ho annullato il ciclo. Tuttavia, ci sarebbe una piccola finestra in cui l'attività pianificata avrebbe sovrascritto il file e il mio ciclo sarebbe ancora sleeping. Quindi, la configurazione di un socket di controllo all'inizio avrebbe permesso al mio script SSH in seguito senza problemi:

#! /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"

Dove setup-ssh.shè:

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"

La sequenza è la seguente:

  • Lo script principale (mostrato per primo) fonti setup-ssh.sh.
  • setup-ssh.shoccupato-loop i server fino a quando tutti hanno una configurazione socket di controllo. Il hostsfile elenca semplicemente i nomi host del server uno per riga.
  • Poiché la configurazione che specifica il socket di controllo è attiva ${CONFIG_DIR}/scripts/.ssh-config, a meno che non specifichi tale file utilizzando -F, le connessioni SSH non lo utilizzeranno. Quindi questo mi permette di usare la presa di controllo solo dove ne ho bisogno usando l' Fopzione.
  • Lo script di installazione copia anche lo script di esecuzione del test sui server. Lo stesso script di esecuzione contiene una serie di comandi e, poiché ho copiato lo script di esecuzione, non devo preoccuparmi di un ulteriore livello di quotazione per SSH (e del sovraccarico cognitivo aggiuntivo per capire cosa viene espanso quando).
  • Quindi lo script principale utilizza xargsper distribuire il carico di lavoro sui server, avviando nuovi lavori non appena terminati.
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.