SSH powoduje zatrzymanie pętli while

30

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.

Johan
źródło
7
SSH może czytać ze standardowego wejścia, pochłaniając twoje actionlist. Spróbuj przekierować standardowe wejście ssh na/dev/null
BatchyX
Spróbuję tego. Chcę dodać, że umieszczenie ssh w opakowaniu nie pomaga ...
Johan
Masz rację. Jak mogłem tego nie zobaczyć !?
Johan
@BatchyX Myślę, że twój komentarz kwalifikuje się jako odpowiedź.
CVn
Zgadzam się, że chciałbym „zaakceptować” odpowiedź, więc jeśli @BatchyX może ją ponownie opublikować jako taką, zrobię to.
Johan

Odpowiedzi:

43

SSH może czytać ze standardowego wejścia, pochłaniając twoją listę akcji. Spróbuj przekierować standardowe wejście ssh na / dev / null:

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

Zasadniczo podczas uruchamiania poleceń, które mogą zakłócać standardowe wejście w while readpętli typu, lubię zawijać całe ciało pętli w nawiasy klamrowe:

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
BatchyX
źródło
3
Podwójnie niesamowite za po pierwsze specyficzne użycie nawiasów klamrowych ... których nigdy nie spotkałem przez 20 lat pisania skryptów (przynajmniej nie, że pamiętam.) I wnioskowania uuoc. FWIW (i we własnej obronie) czasami robię wyjątek i dodam zbędne wypowiedzi kotów ze względu na czytelność! Uwielbiam to forum, ponieważ nagle uczę się nowych rzeczy! W szczególności lubię dodawać przekierowania na początku linii takich jak ten przypadek, ale na forach wydaje się to mylić sprawę, powodując, że otrzymuję mniej przydatnych odpowiedzi!
Johan
Próbowałem ustalić różnicę między {...} a (...) stroną podręcznika ksh mówi, że {...} to specjalne słowa kluczowe rozpoznawane dopiero na początku wiersza poleceń. Ale jest jeszcze jedna różnica ... ( </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 ...
Johan
5
Ponadto ssh OpenSSH ma -nopcję, która powoduje (skuteczne) ponowne otwarcie standardowego wejścia z / dev / null.
Chris Johnsen
Jakieś obejścia korzystania sudoz polecenia w pętli?
bonh
Kiedyś używałem -n od wieków iw pewnym momencie straciłem przyzwyczajenie ... a teraz znów wiem, dlaczego to zrobiłem, po krótkiej chwili spędzonej na kopaniu ...
Florian Heigl