I've to run a command iptables --flush in 100+ servers. I don't have root credentials, but have sudo access for my account. So I come up with a below script to run the command in all servers.

I added the servers names in the flushhosts file.

[root@~]# cat testscript.sh

> for i in `cat /flushhosts`
> do
> sshpass -p 'Mypwd' ssh -t username@$i sudo /sbin/iptables --flush
> cat << EOF || "Mypwd"
> done

[root@~]# ./testscript.sh

./testscript.sh: line 6: syntax error: unexpected end of file

I couldn't find what I'm missing in the script.

  • 1
    Can you tell me what is the purpose of the line cat<<EOF || "Mypwd"? – primero Sep 25 '15 at 12:47
  • I'm providing the sudo password for my account. After executing the 'sudo /sbin/iptables' it will prompt for sudo pwd and so I've added that line. – Kannan AnandaKrishnan Sep 25 '15 at 12:51
  • 1
    this is in fact the problem, bash is expecting a EOF (the word EOF at begin of a line) to close << EOF (this is called a here document) – Archemar Sep 25 '15 at 12:54
  • I added "EOF" in a new line before done. Now looks like it's working.. Thank you. – Kannan AnandaKrishnan Sep 25 '15 at 13:02
  • You mean, there is no more a syntax error ? or sudo is takin Mypwd as password ? – Archemar Sep 25 '15 at 13:04

If you are open to a different approach I would like to propose using expect:

Create a small expect script ex1.sh

#!/usr/bin/expect -f
set arg1 [lindex $argv 0]
spawn ssh username@$arg1
expect "password: "
send "Mypwd\r"
expect "$ "
send "sudo /sbin/iptables --flush\r"
expect "password "
send "Mypwd\r"
expect "$ "
send "exit\r"

Then you can use it in your loop like this:

for i in $(</flushhosts); do ./ex1 $i; done

You have a lot more flexibility with expect, for this kind of situations.


give try to

for i in $(</flushhosts)

   echo "Mypwd" | sshpass -p 'Mypwd' ssh -t username@$i sudo /sbin/iptables --flush

  • this may work, but it is unclear Mypwd (in echo Mypwd) will make its way to sudo
  • $(</flushhosts) is equivalent to $(cat /flushhosts) equiv to back quoted "cat /flushhosts "

about cat << "EOF" || Mypwd

1) cat << "EOF"

This will read lines until the word EOF is encountered, and whole text will be given to cat. this include the done word.

2) || Mypwd

if cat return non zero, then Mypwd (as a command) will be executed.

As no EOF word is found, when bash reach end of document, the for ... do is not close by a done, hence syntax error.

I expect this is not what you want.

the syntax

cat <<EOF 
hello world

is called a here document, this is a way to give data in shell script.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.