使用expect生成带有包含空格的参数的命令

Ric*_*ard 10 bash automation automated-tests expect

我想用来在ssh expect上运行一个简单的命令cat /tmp/id_rsa.pub.

在shell中,我可以运行这个问题,(手动输入密码)

ssh root@localhost 'cat /tmp/id_rsa.pub'
Run Code Online (Sandbox Code Playgroud)

我想用它自动化expect.我的expect剧本是,

#!/usr/bin/expect
eval spawn ssh root@localhost 'cat /tmp/id_rsa.pub'
expect "password:"
send "123456"
expect eof
Run Code Online (Sandbox Code Playgroud)

它抛出错误bash: cat /tmp/id_rsa.pub: no such file or directory.它看起来很奇怪.可能的原因是什么?

编辑:经过一些测试,我发现这很常见,不仅仅是在这种情况下cat.如果生成命令的参数是带空格的(即使它在引号中),它也会有问题.例如,用cat /tmp/id_rsa.pub空格替换其他命令,例如

eval spawn ssh root@localhost 'which java'
Run Code Online (Sandbox Code Playgroud)

它抱怨bash: which java: command not found.但是,如果替换它pwd,就像

eval spawn ssh root@localhost 'pwd'
Run Code Online (Sandbox Code Playgroud)

它工作正常.

Joh*_*uhn 7

'与 sh 和其他兼容 shell 不同,单引号 ( ) 对 Expect 没有特殊意义。
这意味着你的声明

spawn ssh root@localhost 'cat /tmp/id_rsa.pub'
Run Code Online (Sandbox Code Playgroud)

被解析为以下单词:

  • spawn
  • ssh
  • root@localhost
  • 'cat - 直到另一个单引号。
  • /tmp/id_rsa.pub'

sh 中的用法是将其分组为单个参数。在 Tcl 中,您可以使用双引号 ( ") 或大括号 ( {})。在双引号内,Tcl 变量将被替换,而里面的内容{}被传递而没有任何替换1

tl;dr与 sh 等效的 Expect/Tcl'{}.

\换行前的1 A仍将被替换。


小智 5

正如约翰内斯所说,使用'是行不通的。
我遇到了类似的问题,但我想执行更多命令,然后仍然获得登录 shell。我设法使它与"

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}
   }
"
Run Code Online (Sandbox Code Playgroud)


mtk*_*mtk 0

我猜你不需要eval那里。将其拆下并检查。

检查此期望示例链接以获取有关“如何使用expect?”的详细示例 。

希望这可以帮助。