La for
boucle est bien ici. Notez cependant que cela est dû au fait que le fichier contient des noms de machine, qui ne contiennent aucun caractère d’espace ni de caractère de substitution. for x in $(cat file); do …
ne fonctionne pas pour parcourir les lignes de file
en général, car le shell divise d'abord la sortie de la commande cat file
partout où il y a des espaces, puis traite chaque mot comme un motif global afin qu'il \[?*
soit développé davantage. Vous pouvez sécuriser for x in $(cat file)
si vous travaillez dessus:
set -f
IFS='
'
for x in $(cat file); do …
Lecture connexe: Parcourir les fichiers avec des espaces dans les noms? ; Comment puis-je lire ligne par ligne à partir d'une variable dans bash? ; Pourquoi est while IFS= read
utilisé si souvent, au lieu de IFS=; while read..
? Notez qu'en cas d'utilisation while read
, la syntaxe sécurisée pour lire les lignes est la suivante:while IFS= read -r line; do …
.
Voyons maintenant ce qui ne va pas avec votre while read
tentative. La redirection à partir du fichier de liste de serveurs s’applique à l’ensemble de la boucle. Ainsi, lors de son ssh
exécution, son entrée standard provient de ce fichier. Le client ssh ne peut pas savoir quand l'application distante peut vouloir lire à partir de son entrée standard. Ainsi, dès que le client ssh remarque une entrée, il l'envoie au côté distant. Le serveur ssh est alors prêt à alimenter cette entrée avec la commande à distance, s’il le souhaite. Dans votre cas, la commande à distance ne lit jamais d’entrée, les données sont donc ignorées, mais le côté client ne sait rien à ce sujet. Votre tentative avec echo
work car echo
ne lit jamais d’entrée, elle laisse son entrée standard toute seule.
Vous pouvez éviter cela de plusieurs manières. Vous pouvez dire à ssh de ne pas lire depuis l'entrée standard, avec l' -n
option.
while read server; do
ssh -n $server "uname -a"
done < /home/kenny/list_of_servers.txt
L' -n
option indique en fait ssh
de rediriger son entrée /dev/null
. Vous pouvez le faire au niveau du shell et cela fonctionnera pour n'importe quelle commande.
while read server; do
ssh $server "uname -a" </dev/null
done < /home/kenny/list_of_servers.txt
Une méthode tentante à l'entrée de ssh éviter d' entrer dans le fichier est de mettre la redirection sur la read
commande: while read server </home/kenny/list_of_servers.txt; do …
. Cela ne fonctionnera pas, car le fichier sera ouvert à chaque fois que la read
commande est exécutée (la première ligne du fichier sera lue encore et encore). La redirection doit être globalement en boucle while pour que le fichier ne soit ouvert qu'une fois pour la durée de la boucle.
La solution générale consiste à fournir l’entrée à la boucle sur un descripteur de fichier autre que l’entrée standard. L’enveloppe dispose de structures pour acheminer les entrées et les sorties d’un numéro de descripteur à un autre. Ici, nous ouvrons le fichier sur le descripteur de fichier 3 et redirigeons l' read
entrée standard de la commande à partir du descripteur de fichier 3. Le client ssh ignore les descripteurs non standard ouverts, donc tout va bien.
while read server <&3; do
ssh $server "uname -a"
done 3</home/kenny/list_of_servers.txt
Sous bash, la read
commande dispose d'une option spécifique permettant de lire à partir d'un descripteur de fichier différent, afin que vous puissiez écrire read -u3 server
.
Lecture connexe: Descripteurs de fichiers et scripts shell ; Quand utiliseriez-vous un descripteur de fichier supplémentaire?