Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Bash while read loop breaking early [duplicate]

Tags:

bash

shell

People also ask

How do you break a while loop in bash?

Breaking from a while LoopUse the break statement to exit a while loop when a particular condition realizes. The following script uses a break inside a while loop: #!/bin/bash i=0 while [[ $i -lt 11 ]] do if [[ "$i" == '2' ]] then echo "Number $i!" break fi echo $i ((i++)) done echo "Done!"

What is &2 in shell script?

and >&2 means send the output to STDERR, So it will print the message as an error on the console. You can understand more about shell redirecting from those references: https://www.gnu.org/savannah-checkouts/gnu/bash/manual/bash.html#Redirections.

How do you break a loop in Linux?

break command is used to terminate the execution of for loop, while loop and until loop. It can also take one parameter i.e.[N]. Here n is the number of nested loops to break. The default number is 1.

Is there a for loop in bash?

A bash for loop is a bash programming language statement which allows code to be repeatedly executed. A for loop is classified as an iteration statement i.e. it is the repetition of a process within a bash script. For example, you can run UNIX command or task 5 times or read and process list of files using a for loop.


Chris is correct. The source of the loop breaking was SSH using stdin, however guns is correct in is usage of a looping methodology.

If you are looping through input (a file with a list of hostnames for example), and calling SSH, you need to pass the -n parameter, otherwise your loop based on input will fail.

while read host; do
  ssh -n $host "remote command" >> output.txt
done << host_list_file.txt

In the construct

something | 
while read x; do 
    ssh ...
done

the standard input as seen by the while loop is the output of something.

The default behavior of ssh is to read standard input. This allows you to do things like

cat id_rsa.pub | ssh new_box "cat - >> ~/.ssh/authorized_keys"

Now, with that being said, when the first value is read, the first ssh command will read the entire input from something. Then, by the time ssh finishes, there is no output left, and read stops.

The fix is ssh -n ... e.g.

cat /etc/hosts | awk '{print $2}' | while read x; do
    ssh -n $x "do_something_on_the_machine"
done

Most of the answers are specific to ssh. Other commands also hijack stdin and do not have a -n option. This should address any other commands. This should also work for ssh.

while read x; do 
    # Make sure command does not hijack stdin
    echo "" | command $x
done < /path/to/some/file

I ran into this today -- rsh and/or ssh can break a while read loop due to it using stdin. I put a -n into the ssh line which stops it from trying to use stdin and it fixed the problem.


Don't know if it would help, but a cleaner way of writing that would be

for nu in `ruby -e '(0..20).each { |i| puts i}'`; do
  tssh "MYBOXES$nu" 
done

I'm also unsure about why it fails, but i like xargs and seq:

seq 0 20 | xargs -n1 tssh MYBOXES

As Kaii mentioned, it's really overkill to call ruby or seq (which won't work on BSD or OSX machines) just to output a range of numbers. If you're happy with using bash you can:

for i in {0..20}; do
    # command
done

I believe this should work for bash 2.05b and up.