Ssh to an array of servers in a for loop

There are 4 remote hosts that I have stored in an array. A ssh trust has been created from the local host to each of the remote hosts.
I am trying to ssh to each of the servers in a for loop as shown below.

declare -a host
 host[${#host[@]}]="server1"
 host[${#host[@]}]="server2"
 host[${#host[@]}]="server3"
 host[${#host[@]}]="server4"

for host in "${host[@]}"
do
  ssh -qtt user@${host} "sh -s "${version}""  <  test.sh
done

test.sh is a file on the local server that I am running on the remote host after I ssh to the remote host. But it is terminating after the first iteration. If I use -n switch it prompts me for password in the second iteration.

Please can you guide me on this issue.

Thanks!

You cannot double quote double quotes. You could escape them with \, or just use a single quote.

ssh -qtt user@${host} "sh -s '${version}'"  <  test.sh
for host in "${host[@]}"
do
ssh -qtt ohsadm@${host} "sh -s '${version}'"  <  test_steps.sh
done

exits after the first iteration. host array has 4 servers. I want the ssh in the for loop to run through all the 4 servers.

Hi,
Try with -n -o BatchMode=yes options:
-n for manage stdin
-o BatchMode=yes for no ask password

Regards.

You do not want -n when running a script read from stdin! This is not the usual stdin problem.

Can you show your complete, unmodified script? I think something funny is going on here.

I am able to iterate successfully through the array if I specify the commands as mentioned below.

for host in "${host[@]}"
do
  echo $host
  ssh -qtt user@${host} "cd /build && cp -p web.zip web.zip_${version} && rm -rf test && unzip /build/web.zip && cd /bin ";  done;

However, if I try to add the commands in a separate file called test.sh and stream it to ssh as shown below, it exits after the first iteration. Pressing Ctrl-C manually triggers the next iteration.

for host in "${host[@]}"
do
  ssh -qtt user@${host} "sh -s "${version}""  <  test.sh
done

I repeat: You cannot put double quotes inside double quotes that way.

This is wrong:

"sh -s "${version}""

This would be more correct:

"sh -s '${version}'"

I just realized, however -- your test.sh probably uses the ${version} variable, which is why you are feeding it into sh, yes? You want it to carry over. But arguments to sh -s don't work that way, you don't get the names, just $1 $2 $3. Not to mention, you need -- if you want it to assume the following are arguments. Try this:

$ sh -s -- a b c
$ echo $1

a

$ echo $2

b

$ echo $3

c

$ exit
$ 

So I think you actually want:

ssh -qtt user@${host} "sh -s -- '${version}'"  <  test.sh

...and your script should be using $1 and not ${version} .

I suspect you can omit the -tt completely, too. I see no commands in there that actually need a terminal, and throwing one into the mix when not needed seldom helps.

A construct I often use:

ssh username@host exec sh -s -- "arg1" "arg2" "arg3" <<"EOF"

# Literal, unescaped script contents to be executed on the remote side.

echo "arg1 is $1"
echo "arg2 is $2"
echo "arg3 is $3"

# The EOF must be at the beginning of the line and not indented.
EOF

test.sh contains the commands.

ssh -qtt user@$host "sh -s '${version}'" < test.sh

works absolutely fine. I run into issues only while looping.

??? That makes no sense. Why would you feed ssh username@host into ssh username@host ? That instructs the remote host to try and ssh into itself, but will fail because $host and $version are unset and test.sh does not exist. I am extremely suspicious of this ever working, especially since only now have you fixed the syntax errors that I noticed...

This test.sh needs to be a separate file, not the same one, so it can contain this:

cd /build && cp -p web.zip web.zip_${1} && rm -rf test && unzip /build/web.zip && cd /bin

Note the $1 instead of $version, for reasons I gave earlier.

Then you should do

ssh username@host exec /bin/sh -s -- ${version} < test.sh

and have the remote host run the sequence of commands stored in test.sh.

Try it without the -qtt. That may misbehave when you don't have a terminal or want it to be interactive.