forPętli jest tutaj dobrze. Należy jednak pamiętać, że dzieje się tak, ponieważ plik zawiera nazwy maszyn, które nie zawierają żadnych białych znaków ani znaków globowania. generalnie for x in $(cat file); do …nie działa iteracja po liniach file, ponieważ powłoka najpierw rozdziela dane wyjściowe od polecenia w cat filedowolnym miejscu spacji, a następnie traktuje każde słowo jako wzorzec globalny, więc \[?*są one dalej rozwijane. Możesz for x in $(cat file)zabezpieczyć się, jeśli nad tym pracujesz:
set -f
IFS='
'
for x in $(cat file); do …
Czytanie pokrewne: Pętli w plikach ze spacjami w nazwach? ; Jak mogę odczytać wiersz po wierszu ze zmiennej w bash? ; Dlaczego jest while IFS= readużywany tak często, a nie IFS=; while read..? Zauważ, że podczas używania while readbezpieczna składnia do odczytu linii to while IFS= read -r line; do ….
Teraz przejdźmy do tego, co idzie nie tak z Twoją while readpróbą. Przekierowanie z pliku listy serwerów dotyczy całej pętli. Kiedy sshdziała, jego standardowe wejście pochodzi z tego pliku. Klient ssh nie może wiedzieć, kiedy zdalna aplikacja może chcieć czytać ze swojego standardowego wejścia. Gdy tylko klient ssh zauważy jakieś dane wejściowe, wysyła je na stronę zdalną. Serwer ssh jest wtedy gotowy do wprowadzenia tych danych wejściowych do polecenia zdalnego, jeśli tego chce. W twoim przypadku zdalne polecenie nigdy nie odczytuje żadnych danych wejściowych, więc dane zostają odrzucone, ale strona klienta nic o tym nie wie. Twoja próba echozadziałała, ponieważ echonigdy nie czyta żadnych danych wejściowych, pozostawia swoje standardowe dane w spokoju.
Jest kilka sposobów, aby tego uniknąć. Z -nopcją możesz powiedzieć ssh, aby nie czytał ze standardowego wejścia .
while read server; do
ssh -n $server "uname -a"
done < /home/kenny/list_of_servers.txt
Ta -nopcja mówi ssho przekierowaniu danych wejściowych /dev/null. Możesz to zrobić na poziomie powłoki, i zadziała dla każdego polecenia.
while read server; do
ssh $server "uname -a" </dev/null
done < /home/kenny/list_of_servers.txt
Sposób kuszące, aby uniknąć wejścia ssh pochodzące z pliku jest umieścić przekierowanie na readpolecenia: while read server </home/kenny/list_of_servers.txt; do …. To nie zadziała, ponieważ powoduje, że plik jest otwierany ponownie za każdym razem, gdy readkomenda jest wykonywana (aby w kółko czytał pierwszy wiersz pliku). Przekierowanie musi odbywać się w całej pętli while, aby plik był otwierany jeden raz na czas trwania pętli.
Ogólnym rozwiązaniem jest zapewnienie wejścia do pętli w deskryptorze pliku innym niż wejście standardowe. Powłoka ma konstrukcje do przesyłania danych wejściowych i wyjściowych z jednego numeru deskryptora do drugiego. Tutaj otwieramy plik na deskryptorze pliku 3 i przekierowujemy readstandardowe wejście polecenia z deskryptora pliku 3. Klient ssh ignoruje otwarte niestandardowe deskryptory, więc wszystko jest w porządku.
while read server <&3; do
ssh $server "uname -a"
done 3</home/kenny/list_of_servers.txt
W bash readpolecenie ma określoną opcję odczytu z innego deskryptora pliku, więc możesz pisać read -u3 server.
Literatura pokrewna: Deskryptory plików i skrypty powłoki ; Kiedy użyjesz dodatkowego deskryptora pliku?