ssh
está lendo o restante de sua entrada padrão.
while read HOST ; do … ; done < servers.txt
read
lê a partir de stdin. O <
redireciona o stdin de um arquivo.
Infelizmente, o comando que você está tentando executar também lê stdin, então ele acaba comendo o resto do arquivo. Você pode ver claramente com:
$ while read HOST ; do echo start $HOST end; cat; done < servers.txt
start server1.mydomain.com end
server2.mydomain.com
server3.mydomain.com
Observe como cat
comeu (e ecoou) as duas linhas restantes. (Tinha lido feito como esperado, cada linha teria o "início" e "fim" em torno do host.)
Por que for
funciona?
Sua linha for
não redireciona para stdin. (Na verdade, ele lê todo o conteúdo do arquivo servers.txt
na memória antes da primeira iteração). Portanto, ssh
continua a ler seu stdin do terminal (ou possivelmente nada, dependendo de como seu script é chamado).
Solução
Pelo menos no bash, você pode ter read
usando um descritor de arquivo diferente.
while read -u10 HOST ; do ssh $HOST "uname -a" ; done 10< servers.txt
# ^^^^ ^^
deve funcionar. 10
é apenas um número de arquivo arbitrário que eu escolhi. 0, 1 e 2 têm significados definidos e, normalmente, os arquivos de abertura começarão a partir do primeiro número disponível (portanto, 3 estará ao lado). 10 é, portanto, alto o suficiente para ficar fora do caminho, mas baixo o suficiente para estar abaixo do limite em algumas conchas. Além disso, é um bom número redondo ...
Solução Alternativa 1: -n
Como McNisse aponta em sua resposta , o cliente OpenSSH tem uma opção -n
que impedirá a leitura de stdin. Isso funciona bem no caso particular de ssh
, mas é claro que outros comandos podem não ter isso - as outras soluções funcionam independentemente de qual comando está comendo sua stdin.
Solução alternativa 2: segundo redirecionamento
Você pode aparentemente (como em, eu tentei, funciona na minha versão do Bash pelo menos ...) fazer um segundo redirecionamento, que é algo como isto:
while read HOST ; do ssh $HOST "uname -a" < /dev/null; done < servers.txt
Você pode usar isso com qualquer comando, mas será difícil se você realmente quiser que a entrada do terminal vá para o comando.