J'ai finalement réussi à résumer un problème avec lequel je me bats 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 en boucle. La boucle se termine après avoir terminé toute itération avec une commande ssh.
Pendant longtemps, j'ai pensé que c'était une sorte de bizarrerie 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 selon la définition du comportement de l'option "-H" de la liste zfs.)
Mon échantillon a des systèmes de fichiers ZFS pour la racine où toutes les "zones" ont leur système de fichiers racine sur un ensemble de données nommé similaire à
PISCINE / zones / app1zone
PISCINE / zones / group2 / app2zone
etc.
La boucle ci-dessus doit 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 exemple, par 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 provoquer des problèmes avec la longueur de ligne de commande étendue maximale.
Je suis maintenant sûr à 99,999% que seules les boucles contenant des commandes ssh me posent des problèmes!
Notez que l'itération dans laquelle la commande ssh s'exécute, se termine! C'est comme si les données envoyé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 deux ou trois exemples de jeux 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 jeux de données.
actionlist
. Essayez de rediriger l'entrée standard de ssh vers/dev/null
Réponses:
SSH peut lire à partir d'une entrée standard, consommer votre liste d'actions. Essayez de rediriger l'entrée standard de ssh vers / dev / null:
En règle générale, lorsque j'exécute des commandes qui peuvent interférer avec l'entrée standard sous une
while read
boucle de style, j'aime encapsuler tout le corps de la boucle entre accolades:la source
( </tmp/file [ -z "$SOMEVAR" ] && awk '{print "X", $0}' )
diffère de la même chose avec les accolades. Je veux dire en termes de sortie produite, pas sur le fait que l'accolade fermante doit être sur une nouvelle ligne ...-n
option qui lui fait (effectivement) rouvrir son stdin depuis / dev / null.sudo
avec la commande à l'intérieur de la boucle?