我有一个自动连接到VPN的脚本,因为我经常需要每天连接和断开几次。 (某些事情,如ScreenHero和GoToMeeting在VPN上失败,而邮件服务器和其他东西在VPN上被阻止,但是我无法连接到Git服务器,除非我在VPN上,并且我正在处理的应用程序无法访问某些后端服务,除非我在VPN上,因此断开连接时开发受限。)
该脚本减轻了麻烦,但我的密码中有$
(通过环境变量VPN_PASSWORD
1 在环境中可用)和密码值在被期望传递给VPN程序之前被插值。
#!/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
}
如何在不让字符串插值的情况下直接传递密码?
更改密码是个问题。使用\
保存它也是一个警察(和可怕的用户体验,因为每次我为此项目 2 提供.project
文件时我都必须输入它。
似乎期望必须有一个解决方案。
是的,我知道窃取我的笔记本电脑的人可能会尝试登录,但是(a)他们必须先进入我的帐户,然后(b)他们在没有我的PIN的情况下失败,通过电话输入,无论如何。
不,密码不会保存到磁盘。我在每个与此项目相关的shell会话中输入一次。
答案 0 :(得分:2)
除非您定义了具有该名称的任何变量,否则您应该首先获得can't read "VPN_PASSWORD": no such variable
。
可以通过Tcl的特殊数组变量env
访问环境变量。
您可以直接使用env(VPN_PASSWORD)
来访问相同内容。
send "$env(VPN_PASSWORD)\r"
参考: env
答案 1 :(得分:1)
在非加引号的heredoc中有shell变量$VPN_PASSWORD
,因此shell将替换该值。假设VPN_PASSWORD='foo$bar'
=&gt;然后期望看到:send "foo$bar\r"
并且您将获得can't read "bar": no such variable
。解决方案是使用{braces}
而不是双引号,因此期望不尝试扩展&#34;内部&#34;变量
send {$VPN_PASSWORD}; send "\r"
您需要单独的send "\r"
,因为将\r
放在大括号内会删除其特殊含义,而Tcl不会让您send {$VPN_PASSWORD}"\r"
这是一个演示:
$ 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
在Tcl中,大括号在shell中就像单引号一样:内部的所有内容都是文字字符。
使用环境传递值可能更清晰。这里它被实现为shell函数
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
}