forDöngü burada gayet iyi. Ancak bunun, dosyanın boşluk karakterleri veya globbing karakterleri içermeyen makine isimlerini içerdiğinden kaynaklandığını unutmayın. genel olarak for x in $(cat file); do …çizgileri üzerinde yineleme yapmak için çalışmaz file, çünkü kabuk önce çıktıyı komuttan cat fileboşluk olan herhangi bir yere böler ve sonra her kelimeyi bir küre şekli olarak ele alır, böylece \[?*daha da genişler. Üzerinde for x in $(cat file)çalışırsanız güvenli yapabilirsiniz :
set -f
IFS='
'
for x in $(cat file); do …
İlgili okuma: Adlarda boşluk bulunan dosyalar arasında dolaşmak. ; Bir değişkenden bash satır satır satır nasıl okuyabilirim? ; Bunun yerine neden while IFS= readbu kadar sık kullanılıyor IFS=; while read..? Kullanırken while read, satırları okumak için güvenli sözdizimi olduğunu unutmayın while IFS= read -r line; do ….
Şimdi, while readdenemenizde neyin yanlış gittiğine bakalım . Sunucu listesi dosyasından yeniden yönlendirme, tüm döngüye uygulanır. Yani sshçalıştığında, standart girdi o dosyadan gelir. Ssh istemcisi, uzak uygulamanın ne zaman standart girişinden okumak isteyebileceğini bilemez. Böylece ssh istemcisi bazı girişleri fark ettiğinde, o girişi uzak tarafa gönderir. Buradaki ssh sunucusu bu girişi isterse uzak komuta beslemeye hazırdır. Sizin durumunuzda, remote komutu hiçbir zaman herhangi bir girişi okumaz, böylece veriler biter, ancak müşteri tarafı bunun hakkında hiçbir şey bilmez. echoÇalıştığınız girişim echohiç bir girişi okumadığı için standart girişi tek başına bırakır.
Bundan kaçınmanın birkaç yolu vardır. Ssh -nseçeneğine standart girdiden okumamasını söyleyebilirsiniz .
while read server; do
ssh -n $server "uname -a"
done < /home/kenny/list_of_servers.txt
-nAslında seçenek söyler sshonun girişini yönlendirmek için /dev/null. Bunu kabuk düzeyinde yapabilirsiniz ve herhangi bir komut için işe yarar.
while read server; do
ssh $server "uname -a" </dev/null
done < /home/kenny/list_of_servers.txt
Önlemek ssh'nin giriş dosyasından çıkan A cazip yöntem üzerinde yeniden yönlendirme koymaktır readkomutu: while read server </home/kenny/list_of_servers.txt; do …. Bu çalışmaz, çünkü readkomut her çalıştırıldığında dosyanın tekrar açılmasına neden olur (böylece dosyanın ilk satırını tekrar tekrar okuyacaktır). Yeniden yönlendirmenin tüm döngü boyunca olması gerekir, böylece dosya döngü süresince bir kez açılır.
Genel çözüm, standart girdi dışındaki bir dosya tanımlayıcısındaki döngüye girdi sağlamaktır . Kabuk, giriş ve çıkışı bir tanımlayıcı numaradan diğerine feribot yapacak şekilde inşa edilmiştir. Burada dosyayı dosya tanımlayıcı 3'te açıyoruz ve readkomutun standart girişini dosya tanımlayıcı 3'ten yeniden yönlendiriyoruz . Ssh istemcisi standart olmayan açıklayıcıları görmezden geliyor.
while read server <&3; do
ssh $server "uname -a"
done 3</home/kenny/list_of_servers.txt
Bash'ta, readkomutun farklı bir dosya tanımlayıcısından okumak için belirli bir seçeneği var, böylece yazabilirsiniz read -u3 server.
İlgili okuma: Dosya tanımlayıcıları ve kabuk komut dosyası ; Ne zaman ek bir dosya tanımlayıcı kullanırsınız?