Bash 脚本中的 Expect
我编写了一个包含 Expect 的 Bash 脚本,用于连接到终端服务器并清除线路。
我无法弄清楚我遇到的错误,因为我已经给出了所有必要的大括号。我也不明白无法读取文件“line”:没有这样的文件或目录
错误。 我该如何解决这个问题?
我的脚本:
#!/bin/bash
VAR=$(expect -c "
spawn telnet 1.1.1.1
expect {
"Password:" { send "password\r" ; exp_continue}
"Prompt>" { send "en\r" ; exp_continue}
"Password:" { send "password\r" ; exp_continue}
"Prompt#" {send "clea line 10\r" ; exp_continue}
"[confirm]" {send "Y\r" ; exp_continue}
"Prompt#" {send "clea line 11\r" ; exp_continue}
"[confirm]" {send "Y\r" ; exp_continue}
"Prompt#" {send "exit\r" }
}
")
echo $VAR
其输出:
missing close-brace
while executing
"expect"
couldn't read file "line": no such file or directory
I wrote a Bash script with Expect within, to connect to a terminal server and clear lines.
I am unable to figure out the error I am getting, as in I have given all the braces necessary. I also do not understanding the couldn't read file "line": no such file or directory
error.
How can I fix this?
My script:
#!/bin/bash
VAR=$(expect -c "
spawn telnet 1.1.1.1
expect {
"Password:" { send "password\r" ; exp_continue}
"Prompt>" { send "en\r" ; exp_continue}
"Password:" { send "password\r" ; exp_continue}
"Prompt#" {send "clea line 10\r" ; exp_continue}
"[confirm]" {send "Y\r" ; exp_continue}
"Prompt#" {send "clea line 11\r" ; exp_continue}
"[confirm]" {send "Y\r" ; exp_continue}
"Prompt#" {send "exit\r" }
}
")
echo $VAR
Its output:
missing close-brace
while executing
"expect"
couldn't read file "line": no such file or directory
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
第一个问题是 shell 不会按照您的意愿解释嵌套双引号。解决此问题的最简单方法是将 Expect 程序放在单引号中。只要 Expect 程序本身没有单引号就足够了。
您将遇到的下一个问题是,将所有模式和操作放在单个
expect
命令中将并行处理它们。实际发生的情况是,第一个Password:
模式在任何时候看到该字符串时都会匹配(即,即使是第二次的管理员密码)。如果两个密码需要不同,这将是一个问题。至少,相同的模式需要进入单独的expect
命令,以便可以顺序执行。此问题还会影响Prompt#
模式,您会查找该模式三次并希望发送三个不同的响应。稍后,在发送第一个清除命令后,您将收到错误消息。 Expect 解释双引号内的方括号的方式类似于 shell 解释
$()
或``
(即命令替换)的方式。您将看到如下错误:它正在尝试将
confirm
作为 Tcl(或 Expect)命令运行。您可以使用大括号 ({}
) 来阻止 Tcl 进行此解释。此外,默认情况下,期望模式被视为“glob”表达式(即像 shell 通配符),因此即使您编写{[confirm]}
作为模式,它仍然不会用于精确的表达式。字符串匹配(它将匹配任何单个字符c
、o
、n
、f
、i< /code>、
r
或m
)。您必须使用-ex
标志来标记模式以进行精确匹配。解决这些问题,删除一些不必要的引用,你可能会得到这样的结果:
The first problem is that the shell does not interpret nested double quotes as you might like. The easiest way to fix this is to put the Expect program in single quotes. This will be sufficient as long as there are no single quotes in the Expect program itself.
The next problem you will run into is that having all the patterns and actions in a single
expect
command will process them in parallel. What is actually happens is that the firstPassword:
pattern will match any time it sees that string (i.e. even for the admin password the second time around). This will be a problem if the two passwords need to be different. At a minimum, identical patterns will need to go into separateexpect
commands so that they can be executed sequentially. This problem also affects thePrompt#
pattern where you look for it three times and want to send three different responses.Later, you will get an error after you send the first clear command. Expect interprets square brackets inside double quotes in a way that is similar to how shells interpret
$()
or``
(i.e. command substitution). You will see an error like this:It is trying to run
confirm
as a Tcl (or Expect) command. You can use curly brackets ({}
) to prevent Tcl from making this interpretation. Furthermore, expect patterns are treated as “glob” expressions by default (i.e. like shell wildcards), so even if you write{[confirm]}
as the pattern, it will still not be used for an exact string match (it would match any single characterc
,o
,n
,f
,i
,r
, orm
). You must use the-ex
flag to mark the pattern for exact matching.Fix these issues, drop some of the unnecessary quoting, and you might end up with something like this:
问题在于 Expect 脚本中的双引号被视为 Expect 脚本的结尾。尝试将单引号与双引号混合:
The problem is that that the double quotes in the Expect script are treated as the end of the Expect script. Try mixing single quotes with double quotes:
@Chris:我合并了您建议的更改,我的代码现在正在运行。
但是,我还必须进行以下两项更改:
您提到的单引号会阻止参数替换。例如,我无法用
$IP
代替1.1.1.1
。因此,为了解决这个问题,我删除了单引号并替换为双引号。正如您提到的,Bash 不会解释嵌套双引号,这是事实。因此我将内部双引号重写为即在里面的双引号前添加反斜杠。这纠正了参数替换的问题。
即使我在一个 Expect 命令中放置了两个/三个操作,因为它们并行运行,我仍然遇到问题。因此,根据您的建议,我将每个操作放在单独的 Expect 命令中。像这样的东西:
<前><代码>期望{
提示> { 发送“en\r”; exp_继续 }
}
预计 {
密码:{发送“密码2\r”}
}
@Chris: I incorporated the changes you suggested and my code is working now.
However, I had to make two more changes stated below:
The single quote which you mentioned prevents parameter substitution. For example, I cannot write
$IP
in place of1.1.1.1
. Hence, to get around this, I removed the single quotes and replaced with double quotes. As you mentioned nested doubles quotes are not interpreted by Bash which is true. Hence I rewrote the inside double quotes asThat is adding backslashes before the double quotes inside. This corrects the problem of parameter substitution.
Even after I put two/three actions within a single expect command, as they run in parallel I still faced issues. So taking your suggestion, I put each of the action in a separate Expect command. Something like: