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?
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 Input
Output
et Partition
où vous l'exécutiez.
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
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
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 sleep
ing. 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"
Où 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:
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.${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
.xargs
pour répartir la charge de travail sur les serveurs, en démarrant de nouveaux travaux dès la fin de ceux-ci.