Asad Javed
Asad Javed

Reputation: 57

I am trying to integrate expect script into bash script but I am getting an error related to expect scripting

#!/bin/bash

for i in "$@"; do
        echo "Tart #: $i"

        case "$i" in
        
        1)
        IP=10.171.0.10
        ;;
        2)
        IP=10.171.0.11
        ;;
        3)
        IP=10.171.0.12
        ;;
        *)
        echo "Invalid TARTS '$i'" >&2;
        exit 1
        ;;
        esac

        echo "    ----  Launching Tart $i  ----  "
                sshpass -p "tart123" ssh -Y -X -L 5900:$IP:5901 tarts@$IP <<EOF
                  export DISPLAY=:1
                gnome-terminal -e "bash -c \"pwd; cd /home/tarts; pwd; ./launch_tarts.sh exec bash\""
                exit
EOF
done

/usr/bin/expect - << EOF

set tart_num [lindex $argv 0]

puts "Tarts to be updated: $tart_num"

for { set index 0 } { $index < [llength $tart_num] } { incr index } {
 puts "In Loop: $index"
 puts "Tart Num: [lindex $tart_num $index]"
switch -- [lindex $tart_num $index]\
1 {
    spawn telnet 10.171.0.10 6187
        set timeout -1
        expect {
                "*traffic*" { 
        puts "``````````````````````````````````````````````````````````````"
        puts "Registering Group1, Group2"
                send "traffic map rate reg_group1 0\r"
                send "traffic map rate reg_group2 0\r"

                puts "wait 100 seconds .."
                send "traffic go\r"
                sleep 100
        
        sleep 2
        }

        puts "wait 3 seconds"
                sleep 3

                send -- "^]"
                expect -exact "^\]\rtelnet> "
                send -- "close\r"
                expect eof
    }
} 2 {
    spawn telnet 10.171.0.11 6187
        set timeout -1
        expect {
                "*traffic*" {
                puts "``````````````````````````````````````````````````````````````"
                puts "Registering Group1, Group2"
                send "traffic map rate reg_group1 0\r"
                send "traffic map rate reg_group2 0\r"

                puts "wait 100 seconds .."
                send "traffic go\r"
                sleep 100

                sleep 2
                }

                puts "wait 3 seconds"
                sleep 3

                send -- "^]"
                expect -exact "^\]\rtelnet> "
                send -- "close\r"
                expect eof
        }
} 3 {
    spawn telnet 10.171.0.12 6187
        set timeout -1
        expect {
                "*traffic*" {
                puts "``````````````````````````````````````````````````````````````"
                puts "Registering Group1, Group2"
                send "traffic map rate reg_group1 0\r"
                send "traffic map rate reg_group2 0\r"

                puts "wait 100 seconds .."
                send "traffic go\r"
                sleep 100

                sleep 2
                }

                puts "wait 3 seconds"
                sleep 3

                send -- "^]"
                expect -exact "^\]\rtelnet> "
                send -- "close\r"
                expect eof
        }
}
default {
puts "$tart_num is not a valid tart"
}
}
EOF

I have shared my script which is a mixture of bash and expect scripting language. When I try to run it the bash part is running fine but expect script gives an error which is as follows: Tarts to be updated: missing operand at @ in expression " @< [llength ] " (parsing expression " < [llength ] ") invoked from within "for { set index 0 } { < [llength ] } { incr index } { puts "In Loop: " puts "Tart Num: [lindex ]" Can someone please help in integrating the two? The other thing is that the expect script when run separately runs absolutely fine.

Upvotes: 0

Views: 356

Answers (1)

glenn jackman
glenn jackman

Reputation: 247042

All the $tcl_variables are being expanded by the shell before expect even launches. This is because the heredoc is essentially a double-quoted string.

My usual advice is to use a single-quoted heredoc:

# .................v...v
/usr/bin/expect << 'EOF'
... nothing changes in here
EOF

If you have shell variables that you need to use in the expect code, pass them through the environment

# in the shell
export TART="blah blah blah"

expect << 'EOF'
    # retrieve the value from the `env` array
    set tart_num $env(TART)

Fix your indentation. You have non-obvious errors in the expect switch bodies. With correct indentation, the expect code looks like

set tart_num [lindex $argv 0]

puts "Tarts to be updated: $tart_num"

for { set index 0 } { $index < [llength $tart_num] } { incr index } {
    puts "In Loop: $index"
    puts "Tart Num: [lindex $tart_num $index]"
    switch -- [lindex $tart_num $index]\
    1 {
        spawn telnet 10.171.0.10 6187
        set timeout -1
        expect {
            "*traffic*" { 
                puts "``````````````````````````````````````````````````````````````"
                puts "Registering Group1, Group2"
                send "traffic map rate reg_group1 0\r"
                send "traffic map rate reg_group2 0\r"

                puts "wait 100 seconds .."
                send "traffic go\r"
                sleep 100
                sleep 2
            }

            puts "wait 3 seconds"
            sleep 3
            send -- "^]"
            expect -exact "^\]\rtelnet> "
            send -- "close\r"
            expect eof
        }
    } 2 {
        spawn telnet 10.171.0.11 6187
        set timeout -1
        expect {
            "*traffic*" {
                puts "``````````````````````````````````````````````````````````````"
                puts "Registering Group1, Group2"
                send "traffic map rate reg_group1 0\r"
                send "traffic map rate reg_group2 0\r"

                puts "wait 100 seconds .."
                send "traffic go\r"
                sleep 100

                sleep 2
            }

            puts "wait 3 seconds"
            sleep 3

            send -- "^]"
            expect -exact "^\]\rtelnet> "
            send -- "close\r"
            expect eof
        }
    } 3 {
        spawn telnet 10.171.0.12 6187
        set timeout -1
        expect {
            "*traffic*" {
                puts "``````````````````````````````````````````````````````````````"
                puts "Registering Group1, Group2"
                send "traffic map rate reg_group1 0\r"
                send "traffic map rate reg_group2 0\r"

                puts "wait 100 seconds .."
                send "traffic go\r"
                sleep 100

                sleep 2
            }

            puts "wait 3 seconds"
            sleep 3

            send -- "^]"
            expect -exact "^\]\rtelnet> "
            send -- "close\r"
            expect eof
        }
    } default {
        puts "$tart_num is not a valid tart"
    }
}

This part is wrong in each switch branch:

        expect {
            "*traffic*" { 
                puts "``````````````````````````````````````````````````````````````"
                puts "Registering Group1, Group2"
                send "traffic map rate reg_group1 0\r"
                send "traffic map rate reg_group2 0\r"

                puts "wait 100 seconds .."
                send "traffic go\r"
                sleep 100
                sleep 2
            }

            puts "wait 3 seconds"
            sleep 3
            send -- "^]"
            expect -exact "^\]\rtelnet> "
            send -- "close\r"
            expect eof
       }

Bexause you have given the expect command one argument, a list, it is processed as a list of [opt] pattern {action} "pairs". expect actually sees this:

        expect {
            "*traffic*" { 
                puts "``````````````````````````````````````````````````````````````"
                ...
            }
            puts                   {wait 3 seconds}
            sleep                  {3}
            send                   {--}
            "^]"                   {expect}
            -exact "^\]\rtelnet> " {send}
            --     "close\r"       {expect}
            eof
        }

It's syntactically correct, but probably not what you want.
I'm not clear on your intent, so I'm not sure what to advise.

Upvotes: 1

Related Questions