2

Error while executing send if command, Not sure if I'm missing some tcl syntax.

#!/usr/bin/expect -f
# Get the list of hosts, one per line #####
set f [open "/tmp/host.txt"]
set hosts [read $f]
close $f

# Iterate over the hosts
foreach host $hosts {
spawn ssh $host
expect "password: "
send "abcd@123\r"
expect "$ "
send "if [ `df -Ph / | grep -vE '^Filesystem' | awk '{ print $5 " " $1 }' |cut -d'%' -f1` -ge 60 ] ;then  echo "Hi Team- Please check root file system space on `hostname` " | mailx -s "Alert: Almost out of disk space on `hostname`" [email protected] ;fi\r" 
expect "$ " 
send "exit\r" 
expect eof     }

===Error===

[root@hzavks01~]# extra characters after close-quote
    while executing
"send "if [ `df -Ph / | grep -vE '^Filesystem' | awk '{ print $5 " " $1 }' |cut -d'%' -f1` -ge 60 ] ;then  echo "Hi Team- Please check root file system..."
    ("foreach" body line 6)
    invoked from within
"foreach host $hosts {
spawn ssh $host
expect "password: "
send "abcd@123\r"
expect "$ "
send "if [ `df -Ph / | grep -vE '^Filesystem' | awk '{ print $5..."
    (file "./test.sh" line 10)
muku
  • 41
  • 1
  • 4
  • 8
  • The string that you use with `send` seems to contain double quotes. I'm not sure what `expect` does with double-quoted strings that contain double quotes, but a guess is that you would have to escape the internal ones as `\"`. – Kusalananda Oct 30 '18 at 07:52
  • I tried escaping all the internal " but didn't fixed. I guess missing some syntax for escaping characters in tcl – muku Oct 30 '18 at 07:55
  • 1
    instead of `send "...\r"` write `send {...}; send "\r"` (that is, put everything in braces instead of double quotes, except for the CR, which you send separately). Otherwise, `tcl` will also try to expand the `$5` and `$1` from the awk command, even if you try to escape the double quotes inside `"..."`. –  Oct 30 '18 at 08:16
  • and if you use braces `{...}` instead of double quotes `"..."`, do **not** escape `"` as `\"`. –  Oct 30 '18 at 08:24
  • Tcl/Expect syntax is quite tricky. take a look at [*sexpect*](https://github.com/clarkwang/sexpect) with which you can write *Expect* scripts with shell code only. – UNIX.root Oct 30 '18 at 09:54

2 Answers2

3

TCL is simple. In this case as mosvy indicates in the comments use {...} to disable interpolation of the tricky shell code. However the \r to input the command must not be escaped, and the send procedure wants a single string, so either join the string together or use two send calls:

#!/usr/bin/env expect
catch {exec rm foo}
log_file expect.log
spawn -noecho sh
expect -ex {$ }
send {df | awk '/\//{print $NF}' > foo}
send "\r"
expect -ex {$ }
send -- {exit}
send "\r"
expect eof

This might be improved on with a sendline procedure for the task that keeps the \r bit from cluttering up the code:

#!/usr/bin/env expect
proc sendline {line} { send -- "$line\r" }
spawn -noecho sh
expect -ex {$ }
sendline {df | awk '/\//{print $NF}' > foo}
expect -ex {$ }
sendline "exit"
expect eof

If you do need interpolation then backwhacking will be necessary, though in that case it might be better to eliminate the shell code and instead call a program directly on the remote system that performs the necessary task or produces the necessary output in an easy to consume form.

thrig
  • 34,333
  • 3
  • 63
  • 84
  • Very clean solution. – glenn jackman Oct 31 '18 at 14:26
  • very good answer! I wish you or someone else could have made an answer like this one [on](https://unix.stackexchange.com/questions/640935/prevent-expect-from-hanging-when-running-through-ssh) [some](https://unix.stackexchange.com/questions/640793/send-ctrlc-to-script-running-through-ssh) [other](https://unix.stackexchange.com/questions/640396/automating-vncserver-with-expect-not-working-as-expected) related questions I made ;) – Nordine Lotfi May 26 '21 at 15:10
1

I got mine working by setting the username and password at the start of script.

set Username "END_USER"

Imagine my password was pas\Sw)/ord

I had to set the special characters in hex, where hex for

\ is \x5c

) is \x29

/ is \x2f

So I had to set it in using the syntax below without " at the beginning and " at the end.

set Password pas\x5cSw\x29\x2ford

hex values can be found at http://defindit.com/ascii.html

You can also use

puts "$Username"

puts $Password

to echo the values for verification purpose.

Reinstate Monica
  • 663
  • 8
  • 21