I write a deployAll.sh, which read ip_host.list line by line, then add group for all the remote hosts,
when I run: sh deployAll.sh
results:
Group is added to 172.25.30.11
not expected results:
Group is added to 172.25.30.11
Group is added to 172.25.30.12
Group is added to 172.25.30.13
Why it just execute the first one? please help, thanks a lot!
deployAll.sh
#!/bin/bash
function deployAll()
{
while read line;do
IFS=';' read -ra ipandhost<<< "$line"
ssh "${ipandhost[0]}" "groupadd -g 1011 test"
printf "Group is added to ${ipandhost[0]}\n"
done < ip_host.list
}
deployAll
ip_host.list
172.25.30.11;test-30-11
172.25.30.12;test-30-12
172.25.30.13;test-30-13
Without the
ssh
command (which wouldn't make sense on my network), I get the expected output so I suspect that thessh
command is swallowing the remaining standard input. You should use the-n
flag to preventssh
from reading fromstdin
(equivalent to redirectingstdin
from/dev/null
):or
See also How to keep script from swallowing all of stdin?
That's a frequent problem which is caused by the special behavior of
ssh
, which sucks up stdin, starving the loop ( i.e.while read line;do ...;done
)Please see Bash FAQ 89 which discusses this subject in detail.
I also just answered ( and solved ) a similar question regarding
ffmpeg
with the same behavior asssh
in this case. Here: When reading a file line by line, I only get to execute ffmpeg on the first line.TL;DR :
There are three main options:
ssh
's-n
option. Quoted fromman ssh
:Adding a
</dev/null
at the end ofssh
's line ( i.e.ssh ... </dev/null
) will fix the issue and will makessh
behave as expected.Let
read
read from a File Descriptor which is unlikely to be used by a random program: