Search code examples
linuxbashexpect

Expect script - quotes needed with send string conflict with quotes required by expect


I'm trying to use expect to remotely login into a server a change a user password. The application requires that if the password you want to change contains special characters that it be quoted. Problem is, the expect send statement needs to be quoted as well, and when I try and combine the two, the script fails. If I remove the quotes from around the password and use no special characters it runs fine.

send "CHANGEUSERPASSWORD $username PASSWORD "etdgsfdh$"\r" 

If I use the line above and run the script I get

extra characters after close-quote
while executing
"send "CHANGEUSERPASSWORD $username PASSWORD "e"

Also, it seems to dislike only the $ character as I can append a @ to the end of the password without enclosing it in quotes and the script runs fine. How can I get this to work using a password that contains a $ which requires me to wrap it in quotes, which then apparently conflicts with expect quoting? Please note that the $ can be anywhere in the password, not just at the end as in my example.

Here is my full script for context:

#!/usr/bin/expect -f

set password [lindex $argv 0];

spawn telnet 192.168.100.100 106
expect "200 PWD Server ready"
send "USER user\r"
expect "300 please send the PASS"
send "PASS pass\r"
expect "200 login OK, proceed"
send "CHANGEUSERPASSWORD $username PASSWORD "etdgsfdh$"\r"
expect "200 OK"
send "quit\r"
interact

I have also tried to set the password as a variable using this line:

set password [lindex $argv 0];

And changing this line:

send "CHANGEACCOUNTPASSWORD user PASSWORD $password;" send "\r"

Then I run

./script password

and I get this error:

usage: send [args] string
while executing
"send "CHANGEUSERPASSWORD user PASSWORD $password;" send "\r""

What am I doing wrong?


Solution

  • You can simply escape the inner quotes

    send "CHANGEUSERPASSWORD $username PASSWORD \"etdgsfdh$\"\r"
    

    Note that a $ is only special when it's followed by a valid variable name (that may be in braces) -- see http://tcl.tk/man/tcl8.6/TclCmd/Tcl.htm#M12

    I assume you're quoting the password because the remote system needs it to be quoted. To answer your question, you'd do:

    lassign $argv username passwd      # grab the command line arguments
    ...
    send "CHANGEUSERPASSWORD $username PASSWORD \"$passwd\"\r"
    

    If the remote system doesn't require the literal quotes, then simply

    send "CHANGEUSERPASSWORD $username PASSWORD $passwd\r"