GNU/Linux >> Tutoriels Linux >  >> Linux

Ssh provoque l'arrêt de la boucle ?

J'ai enfin réussi à résumer un problème avec lequel je me débattais depuis quelques semaines. J'utilise SSH avec des "clés autorisées" pour exécuter des commandes à distance. Tout va bien sauf quand je le fais dans une boucle while. La boucle se termine après avoir terminé toute itération avec une commande ssh.

Pendant longtemps, j'ai pensé qu'il s'agissait d'une sorte de bizarrerie de ksh, mais j'ai maintenant découvert que bash se comportait en fait de manière identique.

Un petit exemple de programme pour reproduire le problème. Ceci est distillé à partir d'une implémentation plus large qui prend des instantanés et les réplique parmi les nœuds d'un cluster.

#!/bin/bash

set -x

IDTAG=".*zone"
MARKER="mark-$(date +%Y.%m.%d.%H.%M.%S)"
REMOTE_HOST=sol10-target
ZFSPARENT=rpool

ssh $REMOTE_HOST zfs list -t filesystem -rHo name,mounted $ZFSPARENT | grep "/$IDTAG    " > /tmp/actionlist

#for RMT_FILESYSTEM in $(cat /tmp/actionlist)
cat /tmp/actionlist | while read RMT_FILESYSTEM ISMOUNTED
do
   echo ${RMT_FILESYSTEM}@${MARKER}
   [ "$ISMOUNTED" = "yes" ] && ssh $REMOTE_HOST zfs snapshot -r ${RMT_FILESYSTEM}@${MARKER}
   echo Remote Command Return Code: $?
done

(Notez qu'il y a un caractère TAB dans l'expression de recherche grep conformément à la définition du comportement de l'option "-H" de la liste zfs.)

Mon exemple a des systèmes de fichiers ZFS pour la racine où toutes les "zones" ont leur système de fichiers racine sur un jeu de données nommé similaire à

POOL/zones/app1zone
POOL/zones/group2/app2zone

etc.

La boucle ci-dessus devrait créer un instantané pour chacun des ensembles de données sélectionnés, mais à la place, elle ne fonctionne que sur le premier, puis se termine.

Que le programme trouve le bon nombre d'ensembles de données peut être facilement confirmé en vérifiant le fichier "/tmp/actionlist" après que le script existe.

Si la commande ssh est remplacée par, par exemple, une commande echo, la boucle parcourt toutes les lignes d'entrée. Ou mon préféré - ajoutez "echo" à la commande incriminée.

Si j'utilise une boucle for à la place, cela fonctionne également, mais en raison de la taille potentielle de la liste des ensembles de données, cela pourrait causer des problèmes avec la longueur maximale de la ligne de commande étendue.

Je suis maintenant sûr à 99,999 % que seules les boucles contenant des commandes ssh me posent problème !

Notez que l'itération dans laquelle la commande ssh s'exécute se termine ! C'est comme si les données insérées dans la boucle while étaient soudainement perdues... Si les premières lignes d'entrée n'exécutent pas de commande ssh, la boucle continue jusqu'à ce qu'elle exécute réellement la commande SSH.

Sur mon ordinateur portable où je teste cela, j'ai deux machines virtuelles Solaris 10 avec seulement environ deux ou trois exemples d'ensembles de données, mais la même chose se produit sur les grands systèmes SPARC où cela est censé être mis en ligne, et il existe de nombreux ensembles de données.

Connexe :Comment changer le shell cron (sh en bash) ?

Réponse acceptée :

SSH peut lire à partir de l'entrée standard, engloutissant votre liste d'actions. Essayez de rediriger l'entrée standard de ssh vers /dev/null :

ssh $REMOTE_HOST zfs snapshot -r ${RMT_FILESYSTEM}@${MARKER} </dev/null

En règle générale, lors de l'exécution de commandes susceptibles d'interférer avec l'entrée standard sous un while read -boucle de style, j'aime envelopper tout le corps de la boucle dans des accolades :

cat /tmp/uuoc | while read RMT_FILESYSTEM ISMOUNTED
do {
    echo ${RMT_FILESYSTEM}@${MARKER}
    [ "$ISMOUNTED" = "yes" ] && ssh $REMOTE_HOST zfs snapshot -r ${RMT_FILESYSTEM}@${MARKER}
    echo Remote Command Return Code: $?
} < /dev/null; done

Linux
  1. Rappelez-vous une commande à moitié tapée pendant que je vérifie quelque chose ?

  2. Ssh – Restreindre un utilisateur Ssh/scp/sftp à un répertoire ?

  3. Caractère spécial '#' dans la commande Perl Ssh ?

  4. Exemples de boucle Bash For et de boucle While

  5. Utiliser et dans la boucle while de Bash

Bash pendant la boucle

Commande SSH

Comment trouver des connexions SSH actives sous Linux

Comment transmettre un mot de passe à la commande SSH sous Linux

La boucle while dans les scripts shell

Commande Linux pour attendre qu'un serveur SSH soit opérationnel