Quoting issue with expect script -
i have script automatically connect vpn, because have connect , disconnect several times day. (certain things screenhero , gotomeeting fail on vpn, , mail servers , other things blocked while on vpn, but can't connect git server unless i'm on vpn, , app i'm working on can't reach back-end services unless i'm on vpn, development limited when disconnected.)
the script lessens hassle, have $
in password (which available in environment through environment variable vpn_password
1), , password value gets interpolated before passed vpn program expect.
#!/bin/bash { /usr/bin/expect << end_of_login_session set timeout 30 spawn /opt/cisco/anyconnect/bin/vpn -s connect blah.blahblah.com expect "username:*" send "\r" expect "password:*" send "$vpn_password\r" expect "accept? \[y/n\]:*" send "y\r" expect eof end_of_login_session }
how pass password literally, without letting subject string interpolation?
changing password cop-out. saving \
cop-out (and horrible ux, since have enter every time source .project
file project2).
it seems expect must have solution this.
yes know steals laptop try log in, (a) they'd have account first, , (b) they'd fail without pin, entered phone, anyway.
no, password not saved disk. enter once per shell session related project.
you have shell variable $vpn_password
in unquoted heredoc, shell substitute value. suppose vpn_password='foo$bar'
=> expect see: send "foo$bar\r"
, you'll can't read "bar": no such variable
. solution use {braces}
instead of double quotes, expect not attempt expand "inner" variable.
send {$vpn_password}; send "\r"
you need separate send "\r"
because putting \r
inside braces remove special meaning, , tcl won't let send {$vpn_password}"\r"
here's demo:
$ vpn_password='foo$bar' $ expect <<end send_user "$vpn_password\n" end can't read "bar": no such variable while executing "send_user "foo$bar\n"" $ expect <<end send_user {$vpn_password}; send_user "\n" end foo$bar
in tcl, braces act single quotes in shell: inside them literal characters.
it might cleaner use environment pass values. here implemented shell function
vpnconnect() { expect <<'end' set timeout 30 spawn /opt/cisco/anyconnect/bin/vpn -s connect $env(vpn_host) expect "username:*" send "\r" expect "password:*" send "$env(vpn_password)\r" expect {accept? [y/n]:*} send "y\r" expect eof end }