bash and expect in the same script?

24,509
#!/bin/bash
#!/usr/bin/expect -f

Umm... no.

Basically you want for both the programs to read your script, and "do the right thing" regarding every line. Apart from the problems between syncronising the script execution between the interpreters, it's easy to see this is impossible the moment we have a line that could be a valid command in either language.

Consider something like this in your example.

set Username "user" 

It's actually valid in both the shell and in an expect script. In the shell, it sets the positional parameters $1 and $2 to Username and user, respectively. In expect it assigns something else. Which one should it do?

Either split your expect script to a different file and call it from the shell script, or use the fact that Expect runs on TCL which should allow doing loops and IO in itself.


Luckily in this case, there's just an expect snippet contained within a shell loop in your second code block.

So, make a shell script

#!/bin/bash
for i in `seq 2 $NUMERODISP`; do
    IP="$(...)"
    expect -f somename.expect $IP
done

and an expect script to call from the shell script:

#!/usr/bin/expect -f 
set IP   [lindex $argv 0];
spawn telnet $IP
expect "Username:"
send "$Username\r"
...
Share:
24,509

Related videos on Youtube

Cesar Alejandro Villegas Yepez
Author by

Cesar Alejandro Villegas Yepez

Updated on September 18, 2022

Comments

  • Cesar Alejandro Villegas Yepez
    Cesar Alejandro Villegas Yepez almost 2 years

    I'm trying to code an script that takes IP addresses from a .csv file and telnet the device to catch "show version" command output.

    So far I have coded this:

    #!/bin/bash
    #!/usr/bin/expect -f
    FILE1=dispositivos.csv  #file with IP's and device name
    set Username "user"    #this is the user for telnet connection.
    set Password "this.is.the.pass"  #pass for telnet connection.
    
    NUMERODISP="$(wc -l $FILE1 | awk '{print $1}')" #this command counts number of devices (IP's) in the file as it is a .csv file, it only counts number of lines.
    
    
    for i in `seq 2 $NUMERODISP`; 
            do
        IP="$(awk -vnum="$i" 'NR == num { print $NF }' dispositivoss.csv)"
            echo "$IP" #this takes the IP from last column from .csv file
        done    
    

    I need to complete the for loop so it connect via telnet to the IP stored at $IP and save "show version" output.

    I have tried with this:

    for i in `seq 2 $NUMERODISP`;
            do
        IP="$(awk -vnum="$i" 'NR == num { print $NF }' dispositivoss.csv)"
            send "telnet $IP\r"
        expect "Username:"
        send "$Username\r"
        expect "Password: "
        send "$Password\r"
        expect "*>"
        send "show version\r"
        log_file -noappend SN_$IP.dat;
        expect -ex "--More--" {send -- " "; exp_continue}
        expect "*>"
        log_file;
        done    
    

    but it didn't work.

    Is this cause I cannot use bash and expect?

    In case that's the reason.. how can I send $IP and $NUMDISP as a variable into a different expect script? (this is why I think it's different than the other question)

  • Angel Todorov
    Angel Todorov over 7 years
    @cesar, there are ways to put an expect script inside a shell script, but there are always headaches around quoting and variables. This is the cleanest way.