W końcu udało mi się sprowadzić problem, z którym zmagam się od kilku tygodni. Używam SSH z „autoryzowanymi kluczami” do zdalnego uruchamiania poleceń. Wszystko jest w porządku, z wyjątkiem sytuacji, gdy robię to w pętli while. Pętla kończy się po zakończeniu dowolnej iteracji za pomocą polecenia ssh.
Przez długi czas myślałem, że to jakaś dziwność ksh, ale teraz odkryłem, że bash zachowuje się identycznie.
Mały przykładowy program do odtworzenia problemu. Jest to destylowane z większej implementacji, która wykonuje migawki i replikuje je między węzłami w klastrze.
#!/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
(Uwaga: w wyrażeniu wyszukiwania grep występuje znak TAB zgodnie z definicją zachowania opcji „-H” na liście zfs.)
Mój przykład ma niektóre systemy plików ZFS dla katalogu głównego, w którym wszystkie „strefy” mają swój główny system plików w zestawie danych o nazwie podobnej do
POOL / zone / app1zone
POOL / zone / group2 / app2zone
itp.
Powyższa pętla powinna utworzyć migawkę dla każdego z wybranych zestawów danych, ale zamiast tego działa tylko na pierwszym, a następnie kończy działanie.
To, że program znajdzie odpowiednią liczbę zestawów danych, można łatwo potwierdzić, sprawdzając plik „/ tmp / actionlist” po istnieniu skryptu.
Jeśli polecenie ssh zostanie zastąpione na przykład przez polecenie echo, wówczas pętla przechodzi przez wszystkie linie wejściowe. Lub mój ulubiony - dodaj „echo” do niepoprawnego polecenia.
Jeśli zamiast tego użyję pętli for, to również działa, ale ze względu na potencjalny rozmiar listy zestawów danych może to powodować problemy z maksymalną rozszerzoną długością wiersza poleceń.
Jestem teraz 99,999% pewien, że tylko te pętle z komendami ssh sprawiają mi problemy!
Zauważ, że iteracja, w której działa polecenie ssh, została zakończona! To tak, jakby dane przesyłane do pętli while nagle zostały utracone ... Jeśli kilka pierwszych linii wejściowych nie wykona polecenia ssh, wówczas pętla będzie kontynuowana, dopóki nie uruchomi polecenia SSH.
Na moim laptopie, na którym testuję, mam dwie maszyny wirtualne Solaris 10 z tylko około dwoma lub trzema przykładowymi zestawami danych, ale to samo dzieje się w dużych systemach SPARC, w których ma to zostać uruchomione, i istnieje wiele zestawów danych.
źródło
actionlist
. Spróbuj przekierować standardowe wejście ssh na/dev/null
Odpowiedzi:
SSH może czytać ze standardowego wejścia, pochłaniając twoją listę akcji. Spróbuj przekierować standardowe wejście ssh na / dev / null:
Zasadniczo podczas uruchamiania poleceń, które mogą zakłócać standardowe wejście w
while read
pętli typu, lubię zawijać całe ciało pętli w nawiasy klamrowe:źródło
( </tmp/file [ -z "$SOMEVAR" ] && awk '{print "X", $0}' )
różni się tak samo z nawiasami klamrowymi. Mam na myśli pod względem wyprodukowanej produkcji, a nie faktu, że zamykający nawias klamrowy musi znajdować się w nowej linii ...-n
opcję, która powoduje (skuteczne) ponowne otwarcie standardowego wejścia z / dev / null.sudo
z polecenia w pętli?