The for
Loop 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 file
pada umumnya, karena shell pertama membagi output dari perintah di cat file
mana 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= read
sering 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 read
usaha Anda . Pengalihan dari file daftar server berlaku untuk seluruh loop. Jadi ketika ssh
dijalankan, 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 echo
berhasil karena echo
tidak 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 -n
opsi.
while read server; do
ssh -n $server "uname -a"
done < /home/kenny/list_of_servers.txt
The -n
pilihan sebenarnya memberitahu ssh
untuk 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 read
perintah: while read server </home/kenny/list_of_servers.txt; do …
. Ini tidak akan berfungsi, karena menyebabkan file dibuka lagi setiap kali read
perintah 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 read
input 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, read
perintah 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?