Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
772 views
in Technique[技术] by (71.8m points)

bash - while loop to read file ends prematurely

The eventual goal is to have my bash script execute a command on multiple servers. I almost have it set up. My SSH authentication is working, but this simple while loop is killing me. When I execute the while loop, reading my file for host names, it works fine when I run a

ssh $HOST "uname -a"

but when I attempt to run another ssh command,

ssh $HOST "oslevel -s"

the while loop ends early! I can't figure it out. Why would the while read do loop run perfectly fine with the first command, but not when the second is added?

I have a simple text file called hosts.list that has 4 hostnames, one per line.

    $ cat hosts.list
    pcced1bip04
    pcced1bit04
    pcced1bo02
    pcced1bo04

    $ cat getinfo.bash
    #!/bin/bash
    set -x
    while read HOST
      do
        echo $HOST
        ssh $HOST "uname -a"
        #ssh $HOST "oslevel -s"
        echo ""
      done  < hosts.list`

When it runs, it works fine. It goes through the file, line by line and gets the results of "uname -a". So everything is fine, right? (Sorry, but I turned on set -x).

    $ ./getinfo.bash
    + read HOST
    + echo pcced1bip04
    pcced1bip04
    + ssh pcced1bip04 'uname -a'
    AIX pcced1bip04 1 6 0001431BD400
    + echo ''

    + read HOST
    + echo pcced1bit04
    pcced1bit04
    + ssh pcced1bit04 'uname -a'
    AIX pcced1bit04 1 6 0001431BD400
    + echo ''

    + read HOST
    + echo pcced1bo02
    pcced1bo02
    + ssh pcced1bo02 'uname -a'
    AIX pcced1bo02 1 6 0009FE2AD400
    + echo ''

    + read HOST
    + echo pcced1bo04
    pcced1bo04
    + ssh pcced1bo04 'uname -a'
    AIX pcced1bo04 1 6 0009FE2AD400
    + echo ''

    + read HOST
    $

The problem occurs when I enable the line [ssh $HOST "oslevel -s"]. When I do, the script only reads the first line of the file, and then stops. Why won't it go onto the other lines?

    $ ./getinfo.bash
    + read HOST
    + echo pcced1bip04
    pcced1bip04
    + ssh pcced1bip04 'uname -a'
    AIX pcced1bip04 1 6 0001431BD400
    + ssh pcced1bip04 'oslevel -s'
    6100-06-02-1044
    + echo ''

    + read HOST
    $

If I had a problem with my script, why would it be working perfectly fine with just the [ssh $HOST "uname -a"] in the while loop?

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Answer

0 votes
by (71.8m points)

If you run commands which read from stdin (such as ssh) inside a loop, you need to ensure that either:

  • Your loop isn't iterating over stdin
  • Your command has had its stdin redirected:

...otherwise, the command can consume input intended for the loop, causing it to end.

The former:

while read -u 5 -r hostname; do
  ssh "$hostname" ...
done 5<file

...which, using bash 4.1 or newer, can be rewritten with automatic file descriptor assignment as so:

while read -u "$file_fd" -r hostname; do
  ssh "$hostname" ...
done {file_fd}<file

The latter:

while read -r hostname; do
  ssh "$hostname" ... </dev/null
done <file

...can also, for ssh alone, can also be approximated with the -n parameter (which also redirects stdin from /dev/null):

while read -r hostname; do
  ssh -n "$hostname"
done <file

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...