1

I am trying to get output of IQN from multiple servers. I am getting the below error.

Error output

spawn /usr/bin/ssh VM2 | /usr/bin/cat /etc/iscsi/initiatorname.iscsi
root@VM2's password:
bash: -c: line 0: syntax error near unexpected token `|'
bash: -c: line 0: `| /usr/bin/cat /etc/iscsi/initiatorname.iscsi'

script

#!/bin/bash

HOSTS="VM2 VM3 VM4 VM1"

read -p "Password: " PASSWORD

for HOST in $HOSTS
do
expect -c "
spawn cat /etc/iscsi/initiatorname.iscsi
    expect {
    "*password:*" { send $PASSWORD\r;interact }
    }
    exit
    "
done

Am I doing something wrong?

2
  • where is spawn in your script? Make sure your code and your error output correspond Nov 8, 2016 at 19:06
  • added spawn in the script but still not getting the output.
    – user155159
    Nov 9, 2016 at 2:51

2 Answers 2

0

First of all, I don't quite understand, what are you trying to achieve.

What I understood that you want to cat /etc/iscsi/initiatorname.iscsi on each server, right ?

But then why do you need to interact with each server?

I'll post solution for the first problem, where you login to each server, and cat file. I can edit solution, if you want to add interact as well.

So first of I decided to write most of the part of the script in expect itself and not pass it using bash. I think this way you'll get more errors.

So here is the bash script that is used as runner, it prompts for password, so that password is not printed or seen (it is not easy to do in expect directly)

#!/bin/bash 

expect_script="./connect_to_many_hosts_and_cat_files.exp"

[ ! -f $expect_script ] && echo expect_script does not exist && exit 1

echo "Please enter a password:"

read -s password

$expect_script $password

Now the expect script itself

#!/usr/bin/expect

if {$argc != 1} {
   puts "please run expect script using bash script"
   puts "that prompts for password"
   exit
}

set password [lindex $argv 0]

# replace hosts names with your host names !!!
set hosts "host1 host2"

foreach host [ split $hosts " " ] {

    set number_of_password_prompts($host) 0

    puts "# "
    puts "# ssh $host"
    puts "# "

    spawn ssh $host
        expect {
            # here I put password check, just in case password is wrong
            # look a bit ugly, but better than nothing
            "Password:" {
                if { $number_of_password_prompts($host) == 0 } {
                    incr number_of_password_prompts($host)
                    puts "# "
                    puts "# Authenticating try $number_of_password_prompts($host)"
                    puts "# "
                    send "$password\r"
                    exp_continue
                } else {
                    puts "# "
                    puts "# Password is wrong"
                    puts "# "
                    exit
                }
            }
            # in case on host /bin/sh or /bin/bash
            "$ " {
                puts "# "
                puts "# cat /etc/iscsi/initiatorname.iscsi"
                puts "# "
                send "cat /etc/iscsi/initiatorname.iscsi \r"
                expect "$ "
            }
            # in case on host /bin/csh
            "% " {
                puts "# "
                puts "# cat /etc/iscsi/initiatorname.iscsi"
                puts "# "
                send "cat /etc/iscsi/initiatorname.iscsi \r"
                expect "% "
            }
            send "exit\r"
            expect eof
            close
        }
}

Last but not the least make sure you chmod +x both files. You can also run expect other way. And also make sure you put proper location of expect. For me it is /usr/bin/expect. For you could be anything else.

Also one important thing. For expect is important what prompt is out there on your servers. If it is /bin/bash you see I've put condition with $ , if it is /bin/csh then you have to add condition with %.

It is very important for you to check how your $PS1 or other prompt will look like after ssh. Script above won't work if your prompt is

    user@host:~>

For that to work, you have to include one more condition in expect

            "> " {
                puts "# "
                puts "# cat /etc/iscsi/initiatorname.iscsi"
                puts "# "
                send "cat /etc/iscsi/initiatorname.iscsi \r"
                expect "> "
            }

Please pay attention to that, I spend many days trying to figure out why things do not work.

-1

Use ansible for this case.

yum install ansible -y
vim /etc/ansible/hosts
[servers]
192.168.0.2
192.168.0.3

ssh-keygen

Copy public key to destination server. After this try to connect to server

ansible servers -m ping

In ansible documentation you can find information about how to rule servers.

1
  • While I agree ansible is better suited for this, that is not an answer to the original question. Feb 4, 2019 at 18:22

You must log in to answer this question.