Il for
ciclo qui va bene. Si noti che ciò è dovuto al fatto che il file contiene nomi di macchine, che non contengono caratteri di spazi bianchi o caratteri globbing. for x in $(cat file); do …
non funziona per scorrere le righe file
in generale, perché la shell prima divide l'output dal comando cat file
ovunque ci sia uno spazio bianco, quindi tratta ogni parola come un modello glob così \[?*
vengono ulteriormente espansi. Puoi for x in $(cat file)
metterti al sicuro se ci lavori:
set -f
IFS='
'
for x in $(cat file); do …
Lettura correlata: scorrere i file con spazi nei nomi? ; Come posso leggere riga per riga da una variabile in bash? ; Perché viene while IFS= read
usato così spesso, invece di IFS=; while read..
? Si noti che quando si utilizza while read
, la sintassi sicura per leggere le righe è while IFS= read -r line; do …
.
Ora passiamo a ciò che non va nel tuo while read
tentativo. Il reindirizzamento dal file elenco server si applica all'intero ciclo. Quindi, quando ssh
viene eseguito, il suo input standard proviene da quel file. Il client ssh non può sapere quando l'applicazione remota potrebbe voler leggere dal suo input standard. Quindi non appena il client ssh nota un input, invia quell'input al lato remoto. Il server ssh è quindi pronto per alimentare quell'input al comando remoto, se lo desidera. Nel tuo caso, il comando remoto non legge mai alcun input, quindi i dati finiscono per essere scartati, ma il lato client non ne sa nulla. Il tuo tentativo ha echo
funzionato perché echo
non legge mai alcun input, lascia solo il suo input standard.
Ci sono alcuni modi per evitarlo. Puoi dire a ssh di non leggere dallo standard input, con l' -n
opzione.
while read server; do
ssh -n $server "uname -a"
done < /home/kenny/list_of_servers.txt
L' -n
opzione infatti dice ssh
di reindirizzare il suo input da /dev/null
. Puoi farlo a livello di shell e funzionerà per qualsiasi comando.
while read server; do
ssh $server "uname -a" </dev/null
done < /home/kenny/list_of_servers.txt
Metodo tentati di ingresso evitano di ssh proveniente dal file è quello di mettere il reindirizzamento del read
comando: while read server </home/kenny/list_of_servers.txt; do …
. Questo non funzionerà, perché fa riaprire il file ogni volta che read
viene eseguito il comando (in modo da leggere più volte la prima riga del file). Il reindirizzamento deve essere nell'insieme ciclo while in modo che il file venga aperto una volta per la durata del ciclo.
La soluzione generale è fornire l'input al loop su un descrittore di file diverso dall'input standard. La shell ha costrutti per trasportare input e output da un numero descrittore all'altro. Qui, apriamo il file sul descrittore di file 3 e reindirizziamo l' read
input standard del comando dal descrittore di file 3. Il client ssh ignora i descrittori non standard aperti, quindi tutto va bene.
while read server <&3; do
ssh $server "uname -a"
done 3</home/kenny/list_of_servers.txt
In bash, il read
comando ha un'opzione specifica per leggere da un descrittore di file diverso, quindi puoi scrivere read -u3 server
.
Lettura correlata: descrittori di file e script di shell ; Quando useresti un descrittore di file aggiuntivo?