use expect to spawn command with arguments containing spaces

49,515

Solution 1

Single quotes (') have no special meaning to Expect, unlike sh and other compatible shells.
This means that your statment

spawn ssh root@localhost 'cat /tmp/id_rsa.pub'

is parsed into the following words:

  • spawn
  • ssh
  • root@localhost
  • 'cat - not until the other single quote.
  • /tmp/id_rsa.pub'

The usage in sh is to group this to a single argument. In Tcl you could either use double quotes (") or curly brackets ({}). Inside double quotes, Tcl variables will be substituted, while the content inside {} is passed without any substitution1.

tl;dr The Expect/Tcl equivalent of sh's ' are {}.

1 A \ before a newline will still be substitued.

Solution 2

As Johannes said, using ' doesn't work.
I had a similar problem, but I wanted to execute more commands and then still get a login shell. I managed to make it work with ":

expect -c "
   set timeout 5;
   spawn ssh -XY $user@$host -t \"cat /etc/motd; bash -l\"
   expect {
      -re \"^Warning.*\" {exp_continue}
      -re \"^.*sword: \" {send \"${PASSWORDS[$user]}\r\"; interact}
   }
"
Share:
49,515
Richard
Author by

Richard

automate all the things: ask me about bash, ant, awk, and hbase

Updated on August 17, 2020

Comments

  • Richard
    Richard almost 4 years

    I want to use expect to run a simple command cat /tmp/id_rsa.pub over ssh.

    In a shell, I can run this wo problem, (with manually put in the password)

    ssh root@localhost 'cat /tmp/id_rsa.pub'
    

    I want to automate this with expect. My expect script is,

    #!/usr/bin/expect
    eval spawn ssh root@localhost 'cat /tmp/id_rsa.pub'
    expect "password:"
    send "123456"
    expect eof
    

    It throws error bash: cat /tmp/id_rsa.pub: no such file or directory. it looks very strange to me. What could be the possible cause?

    Edit: after some testing, I find this is common, not only in the case of cat. If the argument to spawned command is with space (even if it's in the quotes), it will have problem. For example, replacing cat /tmp/id_rsa.pub with other commands with spaces, like

    eval spawn ssh root@localhost 'which java'
    

    it complains with bash: which java: command not found. But if replacing that with pwd, like

    eval spawn ssh root@localhost 'pwd'
    

    it work fine.