expect puts write to file

Rusty Lemur picture Rusty Lemur · Oct 24, 2012 · Viewed 21.7k times · Source

I am writing an expect script that will ssh into several IPs to test their connectivity. I would like to include a "puts" statement to write the result of each test to a file on the machine calling the script. Although I think I'm following the manual for puts to write to a file, it only writes to stdout. Please see the script below. The end result is that the file is created on the local machine, but no output is directed to it. Instead, the output goes to stdout.

#!/bin/bash

USER=user
PASSWORD=password
IPSTART=12.34.56.
OUTFILE="TEST.log"
PROMPT="#"

for IPEND in `seq 200 231`
do

expect -c "
        set timeout 3
        set chan [open $OUTFILE w]
        spawn ssh $USER@$IPSTART$IPEND
                expect -re \".*ssword.*\" {send \"$PASSWORD\n\"}

                expect {
                        -re \".*Are you sure you want to continue connecting.*\" {send \"yes\n\"; exp_continue}
                        -re \".*$PROMPT.*\$.*\"  {puts $chan \"$IPSTART$IPEND\n\"; send \"exit\n\"}
                }

        close $chan
"

done

I'm wondering if there might be an issue with the quoting, but I can't figure it out.

For reference, this is the example from http://www.tcl.tk/man/tcl8.4/TclCmd/puts.htm

set chan [open my.log a]
set timestamp [clock format [clock seconds]]
puts $chan "$timestamp - Hello, World!"
close $chan

Answer

You're probable problem was that you were using double-quotes. Therefore you should escape the literal $ that will be passed to expect (ie. \$chan):

#!/bin/bash

USER=user
PASSWORD=password
IPSTART=12.34.56.
OUTFILE="TEST.log"
PROMPT="#"

for IPEND in `seq 200 231`
do

expect -c "
        set timeout 3
        set chan [open $OUTFILE w]
        spawn ssh $USER@$IPSTART$IPEND
                expect -re \".*ssword.*\" {send \"$PASSWORD\n\"}

                expect {
                        -re \".*Are you sure you want to continue connecting.*\" {send \"yes\n\"; exp_continue}
                        -re \".*$PROMPT.*\$.*\"  {puts \$chan \"$IPSTART$IPEND\n\"; send \"exit\n\"}
                }

        close $chan
"

done