Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Expect within bash script

Tags:

bash

shell

expect

I am trying to implement an expect script into a bash script. Bear with me since I am fairly new to bash/expect.

Here is the expect script that works as intended:

log_user 0

file delete foo.txt

set fh [open foo.txt a]

set servers {xxx@server1 xxx@server2}

foreach s $servers {
spawn ssh $s
expect "password: "
send "PASSWORD\r"
expect "$ "
send "grep "something" /some/log/file.log"
expect "$ " { puts $fh "$expect_out(buffer)"}
send "exit\r"
}

close $fh

Now, I am hoping to include this expect script in a bash script but it is not working as intended.

Here is what I have so far:

#!/bin/bash

XYZ=$(expect -c "
file delete foo.txt

set fh [open foo.txt a]

set servers {xxx@server1 xxx@server2}

foreach s $servers {
spawn ssh $s
expect "password: "
send "PASSWORD\r"
expect "$ "
send "grep "something" /some/log/file.log"
expect "$ " { puts $fh "$expect_out(buffer)"}
send "exit\r"
}

close $fh
")

echo "$XYZ"

The error I am getting is:

command substitution: line 42: syntax error near unexpected token `('
command substitution: line 42: `expect "$ " { puts $fh "$expect_out(buffer)"}'

I'm open to any other ways to implement this! :)

like image 606
Mr. Kaplan Avatar asked Mar 21 '26 19:03

Mr. Kaplan


2 Answers

You can use /usr/bin/expect -c to execute expect commands :

#!/bin/bash

/usr/bin/expect -c ' 

file delete foo.txt

set fh [open foo.txt a]

set servers {xxx@server1 xxx@server2}

foreach s $servers {
spawn ssh $s
expect "password: "
send "PASSWORD\r"
expect "$ "
send "grep "something" /some/log/file.log"
expect "$ " { puts $fh "$expect_out(buffer)"}
send "exit\r"
}

close $fh
'
like image 169
Bertrand Martel Avatar answered Mar 23 '26 12:03

Bertrand Martel


Bertrand's answer is one way to solve your question, but does not explain the problem with what you were doing.

Bash attempts to expand variables inside double quoted strings, so your expect script will see blank spaces where you want to see $servers, $s, and $fh. Further, you have triply-nested sets of double-quoted strings going on that will cause all sorts of problems with parsing the arguments to expect.

It's a matter of opinion, but I think when something gets to a certain point where it's considered a program of its own, it should be separated into a separate file.

#!/usr/bin/expect
log_user 0

file delete foo.txt

set fh [open foo.txt a]

set servers {xxx@server1 xxx@server2}

foreach s $servers {
    spawn ssh $s
    expect "password: "
    send "PASSWORD\r"
    expect "$ "
    send "grep 'something' /some/log/file.log"
    expect "$ " {
        puts $fh "$expect_out(buffer)"
    }
    send "exit\r"
}

close $fh

Make sure it's executable, and then call it from your bash script:

#!/bin/bash
/usr/local/bin/my_expect_script

(To do this really properly, you should set up public key authentication and then you can get rid of expect altogether by running ssh server "grep 'something' /some/log/file.log" directly from bash)

like image 25
miken32 Avatar answered Mar 23 '26 14:03

miken32



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!