Mam następujący skrypt powłoki. Celem jest zapętlenie każdej linii pliku docelowego (którego ścieżka jest parametrem wejściowym skryptu) i wykonanie pracy z każdą linią. Teraz wygląda na to, że działa tylko z pierwszą linią w pliku docelowym i zatrzymuje się po przetworzeniu tej linii. Czy jest coś nie tak z moim skryptem?
#!/bin/bash
# SCRIPT: do.sh
# PURPOSE: loop thru the targets
FILENAME=$1
count=0
echo "proceed with $FILENAME"
while read LINE; do
let count++
echo "$count $LINE"
sh ./do_work.sh $LINE
done < $FILENAME
echo "\ntotal $count targets"
W programie do_work.sh
uruchamiam kilka ssh
poleceń.
bash
shell
ssh
while-loop
bcbishop
źródło
źródło
source
i po prostu wyjść lubexec
. Ale ten kod nie wygląda na prawdziwy, OP zauważyłby, że echo wymaga-e
prawidłowego wyświetlania wiersza ...do_work.sh
uruchomićssh
przez przypadek?do_work.sh
źródło, a także uruchomićdo.sh
zset -x
debugowania.Odpowiedzi:
Problem polega na tym, że
do_work.sh
uruchamiassh
polecenia i domyślniessh
czyta ze stdin, który jest twoim plikiem wejściowym. W rezultacie widzisz tylko pierwszą przetworzoną linię, ponieważssh
zużywa resztę pliku, a pętla while zostaje zakończona.Aby temu zapobiec, przekaż
-n
opcję dossh
polecenia, aby czytał z/dev/null
zamiast stdin.źródło
cat
. Można by pomyśleć, że szczególnie gryzoń byłby tego ostrożny.while read host ; do $host do_something ; done < /etc/hosts
uniknąłby tego. To całkiem uratuje życie, dzięki!httpie
jest kolejnym poleceniem, które domyślnie odczytuje STDIN i będzie miało to samo zachowanie, gdy zostanie wywołane wewnątrz pętli bash lub fish. Użyjhttp --ignore-stdin
lub ustaw standardowe wejście/dev/null
jak powyżej.Bardziej ogólnie, obejściem, które nie jest specyficzne dla tego rozwiązania,
ssh
jest przekierowanie standardowego wejścia dla dowolnego polecenia, które w przeciwnym razie mogłoby zużywaćwhile
wejście pętli.Dodanie
</dev/null
jest tutaj kluczowym punktem (chociaż poprawione cytowanie jest również dość ważne; zobacz także Kiedy zawijać cudzysłowy wokół zmiennej powłoki? ). Będziesz chciał użyć,read -r
chyba że wyraźnie potrzebujesz starszego, nieco dziwnego zachowania, bez którego otrzymujesz-r
.Innym rodzajem obejścia, które jest dość specyficzne,
ssh
jest upewnienie się, że każdessh
polecenie ma powiązane standardowe wejście, np. Poprzez zmianęzamiast tego czytać polecenia z dokumentu tutaj, który dogodnie (w tym konkretnym scenariuszu) wiąże standardowe wejście
ssh
dla poleceń:źródło
Opcja ssh -n zapobiega sprawdzaniu statusu wyjścia ssh podczas używania HEREdoc podczas przesyłania danych wyjściowych do innego programu. Dlatego preferowane jest użycie / dev / null jako stdin.
źródło
<<EOF
Nadpisuje</dev/null
przekierowanie.<<
Przekierowanie podone
to źle.Stało się to ze mną, ponieważ miałem
set -e
igrep
w pętli zwracano bez wyjścia (co daje niezerowy kod błędu).źródło