Ich habe das folgende Shell-Skript. Der Zweck besteht darin, jede Zeile der Zieldatei (deren Pfad der Eingabeparameter für das Skript ist) zu durchlaufen und für jede Zeile zu arbeiten. Jetzt scheint es nur mit der allerersten Zeile in der Zieldatei zu funktionieren und stoppt, nachdem diese Zeile verarbeitet wurde. Stimmt etwas mit meinem Skript nicht?
#!/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"
In do_work.sh
führe ich ein paar ssh
Befehle aus.
bash
shell
ssh
while-loop
Bischof
quelle
quelle
source
und einfach beenden oderexec
. Aber dieser Code sieht nicht echt aus, das OP würde bemerken, dass das Echo den-e
Zeilenvorschub richtig anzeigen muss ...do_work.sh
laufenssh
durch Zufall?do_work.sh
Quelle und laufen auchdo.sh
mitset -x
zum Debuggen.Antworten:
Das Problem ist , dass die
do_work.sh
Läufessh
Befehle und standardmäßigssh
liest aus stdin , die ist Ihre Eingabedatei. Infolgedessen wird nur die erste Zeile verarbeitet, dassh
der Rest der Datei verbraucht wird und Ihre while-Schleife beendet wird.Um dies zu verhindern, übergeben Sie die
-n
Option an Ihrenssh
Befehl, damit dieser/dev/null
anstelle von stdin gelesen wird .quelle
cat
vermeiden . Sie würden denken, dass insbesondere ein Nagetier diesbezüglich vorsichtig sein würde.while read host ; do $host do_something ; done < /etc/hosts
würde es vermeiden. Das ist ein ziemlicher Lebensretter, danke!httpie
ist ein weiterer Befehl, der standardmäßig STDIN liest und unter demselben Verhalten leidet, wenn er in einer Bash- oder Fish-Schleife aufgerufen wird. Verwendenhttp --ignore-stdin
oder setzen Sie die Standardeingabe/dev/null
wie oben beschrieben.Im Allgemeinen besteht eine Problemumgehung, die nicht spezifisch
ssh
ist, darin, die Standardeingabe für jeden Befehl umzuleiten, der andernfalls diewhile
Eingabe der Schleife verbrauchen könnte .Das Hinzufügen von
</dev/null
ist hier der entscheidende Punkt (obwohl das korrigierte Anführungszeichen auch etwas wichtig ist; siehe auch Wann werden Anführungszeichen um eine Shell-Variable gewickelt? ). Sie sollten es verwenden, esread -r
sei denn, Sie benötigen speziell das etwas merkwürdige Verhalten, ohne das Sie auskommen-r
.Eine andere Art von Problemumgehung, die etwas spezifisch ist,
ssh
besteht darin, sicherzustellen, dassssh
die Standardeingabe eines Befehls verknüpft ist, z. B. durch ÄndernLesen Sie stattdessen die Befehle aus einem Dokument, das bequem (für dieses spezielle Szenario) die Standardeingabe
ssh
für die Befehle verknüpft:quelle
Die Option ssh -n verhindert, dass der Exit-Status von ssh überprüft wird, wenn HEREdoc verwendet wird, während die Ausgabe an ein anderes Programm weitergeleitet wird. Daher wird die Verwendung von / dev / null als Standard bevorzugt.
quelle
<<EOF
überschreibt die</dev/null
Umleitung. Die<<
Umleitung nach demdone
ist falsch.Dies geschah mir, weil ich hatte
set -e
und einegrep
in einer Schleife ohne Ausgabe zurückkehrte (was einen Fehlercode ungleich Null ergibt).quelle