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

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/12518354/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-09 22:44:20  来源:igfitidea点击:

use expect to spawn command with arguments containing spaces

bashautomationautomated-testsexpect

提问by Richard

I want to use expectto run a simple command cat /tmp/id_rsa.pubover ssh.

我想用来通过 sshexpect运行一个简单的命令cat /tmp/id_rsa.pub

In a shell, I can run this wo problem, (with manually put in the password)

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

ssh root@localhost 'cat /tmp/id_rsa.pub'

I want to automate this with expect. My expectscript is,

我想用expect. 我的expect剧本是

#!/usr/bin/expect
eval spawn ssh root@localhost 'cat /tmp/id_rsa.pub'
expect "password:"
send "123456"
expect eof

It throws error bash: cat /tmp/id_rsa.pub: no such file or directory. it looks very strange to me. What could be the possible cause?

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

Edit: after some testing, I find this is common, not only in the case of cat. If the argument to spawned command is with space (even if it's in the quotes), it will have problem. For example, replacing cat /tmp/id_rsa.pubwith other commands with spaces, like

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

eval spawn ssh root@localhost 'which java'

it complains with bash: which java: command not found. But if replacing that with pwd, like

它抱怨bash: which java: command not found。但是如果用 替换它pwd,比如

eval spawn ssh root@localhost 'pwd'

it work fine.

它工作正常。

回答by Johannes Kuhn

Single quotes (') have no special meaning to Expect, unlike sh and other compatible shells.
This means that your statment

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

spawn ssh root@localhost 'cat /tmp/id_rsa.pub'

is parsed into the following words:

被解析为以下单词:

  • spawn
  • ssh
  • root@localhost
  • 'cat- not until the other single quote.
  • /tmp/id_rsa.pub'
  • spawn
  • ssh
  • root@localhost
  • 'cat- 直到另一个单引号。
  • /tmp/id_rsa.pub'

The usage in sh is to group this to a single argument. In Tcl you could either use double quotes (") or curly brackets ({}). Inside double quotes, Tcl variables will be substituted, while the content inside {}is passed without any substitution1.

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

tl;drThe Expect/Tcl equivalent of sh's 'are {}.

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

1A \before a newline will still be substitued.

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

回答by genesys87

As Johannes said, using 'doesn't work.
I had a similar problem, but I wanted to execute more commands and then still get a login shell. I managed to make it work with ":

正如约翰内斯所说,使用'不起作用。
我遇到了类似的问题,但我想执行更多命令,然后仍然获得登录 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}
   }
"

回答by mtk

I guess you don't require evalthere. Remove it and check.

我想你不需要eval那里。取出并检查。

Check this expect examples linkfor detailed examples on "how to use expect?" .

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

Hope this helps.

希望这可以帮助。