web-dev-qa-db-fra.com

Plusieurs commandes pendant un SSH dans une session SSH

J'ai une machine locale qui est censée créer une session SSH vers une machine distante master puis une autre session SSH interne de la master vers chacune des slaves distantes, et puis exécutez 2 commandes c'est-à-dire supprimer un répertoire spécifique et le recréer.

Notez que la machine locale a SSH sans mot de passe pour le maître et le maître a SSH sans mot de passe pour les esclaves. Tous les noms d'hôtes sont également connus dans .ssh/config des machines locales/maîtres et les noms d'hôte des esclaves sont dans slaves.txt localement et je les lis à partir de là.

Donc, ce que je fais et travaille est le suivant:

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 

Ce cluster est sur Amazon EC2 et j'ai remarqué qu'il y a 6 sessions SSH créées à chaque itération, ce qui induit un retard important. Je voudrais combiner ces 3 commandes en 1 pour obtenir moins de connexions SSH. J'ai donc essayé de combiner les 2 premières commandes en

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

Mais cela ne fonctionne pas comme prévu. Il semble exécuter le premier (rm -rf Input Output Partition) puis quitte la session et continue. Que puis-je faire?

10
mgus

Considérez que && est un opérateur logique. Cela ne signifie pas signifie "également exécuter cette commande" cela signifie "exécuter cette commande si l'autre réussit".

Cela signifie que si la commande rm échoue (ce qui se produira si l'un des trois répertoires n'existe pas), le mkdir ne sera pas exécuté. Cela ne ressemble pas au comportement que vous souhaitez; si les répertoires n'existent pas, c'est probablement bien de les créer.

tilisation ;

Le point-virgule ; est utilisé pour séparer les commandes. Les commandes sont exécutées séquentiellement, en attendant chacune avant de passer à la suivante, mais leur succès ou leur échec n'a aucun impact les uns sur les autres.

Échapper aux guillemets intérieurs

Les citations à l'intérieur d'autres citations doivent être échappées, sinon vous créez un point final et un point de départ supplémentaires. Votre commande:

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

Devient:

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

Votre commande actuelle, en raison du manque de guillemets échappés, devrait s'exécuter:

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

si cela réussit:

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

Vous remarquerez que la coloration syntaxique montre la commande entière en rouge ici, ce qui signifie que la commande entière est la chaîne transmise à ssh. Vérifiez votre machine locale; vous pouvez avoir les répertoires InputOutput et Partition où vous l'exécutiez.

15
Centimane

Vous pouvez toujours définir dans votre jumpbox Multiplexage dans OpenSSH

Le multiplexage est la possibilité d'envoyer plus d'un signal sur une seule ligne ou connexion. Avec le multiplexage, OpenSSH peut réutiliser une connexion existante TCP pour plusieurs sessions SSH simultanées plutôt que d'en créer une à chaque fois.

Un avantage du multiplexage SSH est que la surcharge de création de nouvelles connexions TCP est éliminée. Le nombre total de connexions qu'une machine peut accepter est une ressource finie et la limite est plus perceptible sur certaines machines que sur d'autres, et varie considérablement en fonction de la charge et de l'utilisation. Il y a également un retard important lors de l'ouverture d'une nouvelle connexion. Les activités qui ouvrent de nouvelles connexions à plusieurs reprises peuvent être considérablement accélérées à l'aide du multiplexage.

Pour cela, faites dans /etc/ssh/ssh_config:

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

De cette façon, toutes les connexions consécutives établies au même serveur dans les 30 minutes suivantes seront effectuées en réutilisant la connexion ssh précédente.

Vous pouvez également le définir pour une machine ou un groupe de machines. Tiré du lien fourni.

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

Vous pouvez mettre toutes vos commandes dans un script séparé sur votre serveur "maître".

Master Script

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

Ensuite, dans votre script ssh, appelez-le comme ceci: 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 si tous les fichiers doivent se trouver sur la machine initiale, vous pouvez faire quelque chose comme ceci:

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
4
jesse_b

Il y a quelque temps, j'ai eu l'occasion d'utiliser des sockets de contrôle comme les autres réponses le recommandent (cette réponse est essentiellement une combinaison d'utiliser des sockets de contrôle comme cette réponse et des scripts comme cette réponse ) .

Le cas d'utilisation était un hack: le authorized_keys de l'utilisateur cible était écrasé périodiquement par une tâche planifiée et je voulais tester rapidement les choses sans passer par la paperasserie nécessaire pour ajouter quelque chose à ce fichier. J'ai donc configuré une boucle while qui a ajouté la clé à ce fichier si nécessaire, exécuté mon test et annulé la boucle. Cependant, il y aurait une petite fenêtre où la tâche planifiée écraserait le fichier et ma boucle serait toujours sleeping. Ainsi, la mise en place d'un socket de contrôle au démarrage laisserait mon script SSH plus tard sans problème:

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

setup-ssh.sh est:

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

Et .ssh-config:

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

Et run-test.sh:

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

La séquence se déroule comme suit:

  • Le script principal (illustré en premier) sources setup-ssh.sh.
  • setup-ssh.sh occupé-boucle les serveurs jusqu'à ce qu'ils aient tous une configuration de socket de contrôle. Le fichier hosts répertorie simplement les noms d'hôte du serveur un par ligne.
  • Étant donné que la configuration spécifiant la prise de contrôle est uniquement dans ${CONFIG_DIR}/scripts/.ssh-config, sauf si je spécifie ce fichier à l'aide de -F, Les connexions SSH ne l'utiliseront pas. Cela me permet donc d'utiliser la prise de contrôle uniquement là où j'en ai besoin en utilisant l'option F.
  • Le script de configuration copie également le script d'exécution du test sur les serveurs. Le script d'exécution lui-même contient un tas de commandes, et parce que j'ai copié le script d'exécution, je n'ai pas à me soucier d'une couche supplémentaire de devis pour SSH (et de la surcharge cognitive supplémentaire pour déterminer ce qui sera développé quand).
  • Ensuite, le script principal utilise xargs pour répartir la charge de travail sur les serveurs, en démarrant de nouveaux travaux dès la fin de ceux-ci.
1
muru