我的目标:自动化从一台服务器到另一台服务器的 scp,获取用户的输入挑战:我无法在服务器之间设置 ssh 授权主机等效性,因为有权访问目标的用户也将有权访问源服务器所以,我需要设置旧方法出现提示时提供密码,然后执行 scp。
这是我的代码
L_SRC_SID=source
L_SID=target
MOUNT_POINT=app07
SERVICE_PASS=some$value
APP_SERVER_1=hostname
SRC_MOUNT_POINT=app01
#And now transfer the file over
/usr/bin/expect -c "
set timeout 1
cd /$MOUNT_POINT/$L_SID/apps
spawn scp -pr * apps@$APP_SERVER_1:/$SRC_MOUNT_POINT/$L_SRC_SID/apps .
expect yes/no { send yes\r ; exp_continue }
expect password: { send $SERVICE_PASS\r }
expect 100%
sleep 1
exit
"
exit
挑战: 1. 我无法将 some$value 值分配给变量 SERVICE_PASS 2. 如何使用密码中包含 $ 字符的变量使 Expect send 脚本工作。它因以下错误而失败。
password: can't read "value": no such variable
任何帮助表示赞赏
我已经按照建议更改了代码,但仍然遇到相同的错误
L_SRC_SID=source
L_SID=target
MOUNT_POINT=app07
SERVICE_PASS='some$value'
APP_SERVER_1=hostname
SRC_MOUNT_POINT=app01
#And now transfer the file over
/usr/bin/expect -c "
set timeout 1
cd /$MOUNT_POINT/$L_SID/apps
spawn scp -pr * apps@$APP_SERVER_1:/$SRC_MOUNT_POINT/$L_SRC_SID/apps .
expect yes/no { send yes\r ; exp_continue }
expect password: { send $SERVICE_PASS\r }
expect 100%
sleep 1
exit
"
exit
这是完整的错误。
password: can't read "value": no such variable
while executing
"send some$value\r "
invoked from within
"expect password: { send some$value\r }"
答案1
对于这种情况,您需要将您的值用单引号引起来:
'some$value'
双引号""
抑制文件名扩展,但不抑制变量扩展。
$ value="some$value"
$ echo $value
some
单引号''
抑制文件名和变量扩展。
$ value='some$value'
$ echo $value
some$value
反引号``
允许变量扩展
$ value=`some$value`
$ echo $value`
$
$
因此,要抑制、!
、"
、等字符的扩展并/
使用单引号!
答案2
因为您在期望脚本主体中使用双引号,所以您必须处理两个都shell变量扩展和expect(即Tcl)变量扩展。当expect运行时,shell变量已被扩展,因此expect会看到:
expect password: { send some$value\r }
所以现在,您需要处理 Tcl 变量。
你可以添加更多引用:
/usr/bin/expect -c "
...
expect password: { send {$SERVICE_PASS}; send \r }
但这不是必需的:我会将 Expect 脚本放在单引号中,并通过环境传递 shell 参数。这样,每个变量只会被替换一次:无论是在 shell 中还是在 Expect 中,并且您不会得到任何意外。
export L_SRC_SID L_SID MOUNT_POINT SERVICE_PASS APP_SERVER_1 SRC_MOUNT_POINT
/usr/bin/expect -c ' # <- single quote
set timeout -1
cd /$env(MOUNT_POINT)/$env(L_SID)/apps
spawn scp -pr * apps@$env(APP_SERVER_1):/$env(SRC_MOUNT_POINT)/$env(L_SRC_SID)/apps .
expect {
yes/no { send yes\r ; exp_continue }
password: { send $env(SERVICE_PASS)\r }
}
expect eof
'
一般来说,使用sleep
inexpect 意味着您要么超时错误,要么期待错误的事情。我都改变了。
答案3
使用'strong quotes'
; $
、!
、"
、等特殊字符\
在其中没有任何意义。