Capita spesso in BASH di realizzare un costrutto che iteri il comando OpenSSH; capita spesso che questo avvenga a partire da una WHILE READ
in quanto questo non è altrimenti sostituibile con un FOR
o con un parallel-ssh
(es. il file di forma tabellare fornisce più di un parametro a OpenSSH).
Esempio
while read HOST USER CMD; do ssh $USER@$HOST "$CMD"; done < lista
Ebbene, quello che otteniamo è l’esecuzione dell’OpenSSH solo in corrispondenza della prima riga del file senza alcun tipo di evidenza di errore. Nella magiorparte dei casi viene data la colpa al costrutto WHILE
o al comando READ
.
Nulla di più falso!
Cosa accade in realtà?
Nella realtà accade che il comando OpenSSH legge da STDIN, e il corpo istruzioni del costrutto WHILE READ
non maschera lo standard input del costrutto, pertanto i comandi all’interno del corpo istruzioni possono attingere al medesimo STDIN. Quindi alla prima esecuzione di OpenSSH, questo consuma l’intero STDIN, lasciando la successiva iterazione priva di altri dati, portandola conseguentemente a corretta conclusione.
Soluzione 1
Utilizzare l’opzione -n del comando OpenSSH
while read HOST USER CMD do ssh -n $USER@$HOST "$CMD" done < lista
Soluzione 2 (valida per somandi anche differenti da OpenSSH)
while read HOST USER CMD do ssh $USER@$HOST "$CMD" < /dev/null done < lista