The forLoop baik-baik saja di sini. Tetapi perhatikan bahwa ini karena file tersebut berisi nama mesin, yang tidak mengandung karakter spasi putih atau karakter globbing. for x in $(cat file); do …tidak bekerja untuk mengulangi garis-garis filepada umumnya, karena shell pertama membagi output dari perintah di cat filemana saja ada spasi, dan kemudian memperlakukan setiap kata sebagai pola gumpalan sehingga \[?*diperluas lebih lanjut. Anda dapat membuat for x in $(cat file)aman jika Anda mengerjakannya:
set -f
IFS='
'
for x in $(cat file); do …
Bacaan terkait: Looping melalui file dengan spasi di namanya? ; Bagaimana saya bisa membaca baris demi baris dari variabel dalam bash? ; Mengapa while IFS= readsering digunakan, bukan IFS=; while read..? Perhatikan bahwa saat menggunakan while read, sintaks aman untuk membaca baris adalah while IFS= read -r line; do ….
Sekarang mari kita beralih ke apa yang salah dengan while readusaha Anda . Pengalihan dari file daftar server berlaku untuk seluruh loop. Jadi ketika sshdijalankan, input standarnya berasal dari file itu. Klien ssh tidak dapat mengetahui kapan aplikasi jarak jauh mungkin ingin membaca dari input standarnya. Jadi begitu klien ssh memperhatikan beberapa input, ia mengirimkan input itu ke sisi jarak jauh. Server ssh di sana kemudian siap untuk memasukkan input itu ke perintah jarak jauh, jika ia menginginkannya. Dalam kasus Anda, perintah jarak jauh tidak pernah membaca input apa pun, sehingga data akhirnya dibuang, tetapi pihak klien tidak tahu apa-apa tentang itu. Upaya Anda dengan echoberhasil karena echotidak pernah membaca input apa pun, ia meninggalkan input standarnya sendiri.
Ada beberapa cara untuk menghindari hal ini. Anda dapat memberitahu ssh untuk tidak membaca dari input standar, dengan -nopsi.
while read server; do
ssh -n $server "uname -a"
done < /home/kenny/list_of_servers.txt
The -npilihan sebenarnya memberitahu sshuntuk mengarahkan input dari /dev/null. Anda dapat melakukannya di level shell, dan itu akan berfungsi untuk perintah apa pun.
while read server; do
ssh $server "uname -a" </dev/null
done < /home/kenny/list_of_servers.txt
Sebuah metode menggoda untuk masukan menghindari ssh ini berasal dari file tersebut adalah untuk menempatkan pengalihan pada readperintah: while read server </home/kenny/list_of_servers.txt; do …. Ini tidak akan berfungsi, karena menyebabkan file dibuka lagi setiap kali readperintah dieksekusi (sehingga akan membaca baris pertama file berulang-ulang). Pengalihan harus pada keseluruhan while sehingga file dibuka sekali selama durasi loop.
Solusi umum adalah memberikan input ke loop pada deskriptor file selain dari input standar. Shell memiliki konstruksi untuk mengangkut input dan output dari satu nomor deskriptor ke yang lain. Di sini, kita membuka file pada file deskriptor 3, dan mengarahkan readinput standar perintah dari file deskriptor 3. Klien ssh mengabaikan deskriptor non-standar terbuka, jadi semuanya baik-baik saja.
while read server <&3; do
ssh $server "uname -a"
done 3</home/kenny/list_of_servers.txt
Di bash, readperintah memiliki opsi khusus untuk membaca dari deskriptor file yang berbeda, sehingga Anda bisa menulis read -u3 server.
Bacaan terkait: File deskriptor & skrip shell ; Kapan Anda akan menggunakan deskriptor file tambahan?