Die for
Schleife ist hier in Ordnung. Beachten Sie jedoch, dass dies daran liegt, dass die Datei Computernamen enthält, die keine Whitespace- oder Globbing-Zeichen enthalten. for x in $(cat file); do …
Das Iterieren über die Zeilen von funktioniert file
im Allgemeinen nicht, da die Shell die Ausgabe des Befehls zunächst an einer cat file
beliebigen Stelle mit Leerzeichen aufteilt und dann jedes Wort als Glob-Muster behandelt, um \[?*
es weiter zu erweitern. Sie können auf Nummer for x in $(cat file)
sicher gehen, wenn Sie daran arbeiten:
set -f
IFS='
'
for x in $(cat file); do …
Weiterführende Literatur: Durchlaufen von Dateien mit Leerzeichen in den Namen? ; Wie kann ich Zeile für Zeile aus einer Variablen in Bash lesen? ; Warum wird while IFS= read
so oft verwendet, anstatt IFS=; while read..
? Beachten Sie, dass bei Verwendung while read
die sichere Syntax zum Lesen von Zeilen lautet while IFS= read -r line; do …
.
Wenden wir uns nun dem zu, was bei Ihrem while read
Versuch schief geht . Die Umleitung aus der Serverlistendatei gilt für die gesamte Schleife. Wenn also ausgeführt wird ssh
, stammt die Standardeingabe aus dieser Datei. Der ssh-Client kann nicht wissen, wann die entfernte Anwendung von ihrer Standardeingabe lesen möchte. Sobald der ssh-Client eine Eingabe bemerkt, sendet er diese Eingabe an die entfernte Seite. Der dortige ssh-Server ist dann bereit, diese Eingabe an den Remote-Befehl weiterzuleiten, falls er dies wünscht. In Ihrem Fall liest der Remote-Befehl niemals Eingaben, sodass die Daten verworfen werden, aber die Clientseite weiß nichts darüber. Ihr Versuch mit hat echo
funktioniert, weil er echo
keine Eingaben liest, sondern seine Standardeingaben in Ruhe lässt.
Es gibt einige Möglichkeiten, wie Sie dies vermeiden können. Mit der -n
Option können Sie ssh anweisen, nicht von der Standardeingabe zu lesen .
while read server; do
ssh -n $server "uname -a"
done < /home/kenny/list_of_servers.txt
Die -n
Option gibt an, dass ssh
die Eingabe von umgeleitet werden soll /dev/null
. Sie können das auf der Shell-Ebene tun, und es wird für jeden Befehl funktionieren.
while read server; do
ssh $server "uname -a" </dev/null
done < /home/kenny/list_of_servers.txt
Eine verlockende Methode zu vermeiden ssh die Eingabe aus der Datei kommt , ist die Umleitung auf den setzen read
Befehl: while read server </home/kenny/list_of_servers.txt; do …
. Dies funktioniert nicht, da die Datei bei jeder read
Ausführung des Befehls erneut geöffnet wird (sodass die erste Zeile der Datei immer wieder gelesen wird). Die Umleitung muss in der gesamten while-Schleife erfolgen, damit die Datei für die Dauer der Schleife einmal geöffnet wird.
Die allgemeine Lösung besteht darin, die Eingabe für die Schleife in einem anderen Dateideskriptor als der Standardeingabe bereitzustellen . Die Shell verfügt über Konstrukte, um die Eingabe und Ausgabe von einer Deskriptornummer zur nächsten zu übermitteln. Hier öffnen wir die Datei in Dateideskriptor 3 und leiten die read
Standardeingabe des Befehls von Dateideskriptor 3 um. Der ssh-Client ignoriert offene Nicht-Standarddeskriptoren, sodass alles in Ordnung ist.
while read server <&3; do
ssh $server "uname -a"
done 3</home/kenny/list_of_servers.txt
In bash hat der read
Befehl eine bestimmte Option zum Lesen aus einem anderen Dateideskriptor, sodass Sie schreiben können read -u3 server
.
Verwandte Lektüre: Dateideskriptoren & Shell-Scripting ; Wann würden Sie einen zusätzlichen Dateideskriptor verwenden?