Bash 脚本中的 Expect:expect_out 不打印缓冲区
我试图通过登录交换机来捕获“dir”命令的输出,但我无法这样做。我在 Bash 中使用 Expect。我正在利用 Expect_out 来捕获缓冲区中该命令的输出并将其打印出来。实际上我想捕获输出并对其执行一些操作。
脚本:
#!/bin/bash
expect -c "
spawn telnet 1.1.1.1 2000
sleep 1
send \"\r\"
send \"\r\"
expect {
Prompt> { send \"dir\r\" }
}
set output $expect_out(buffer)
"
echo "$output"
输出:
spawn telnet 1.1.1.1 2000
Trying 1.1.1.1...
Connected to 1.1.1.1 (1.1.1.1).
Escape character is '^]'.
Prompt>
Prompt>
显示这些提示后,脚本就退出。我该如何解决这个问题?
拆分后,我可以使用参数替换和单引号。现在我面临着不同的错误。
脚本:
expect -c "
spawn telnet $IP $PORT1
sleep 1
send \"\r\"
send \"\r\"
"
expect -c '
expect {
Prompt> { send \"dir\r\" }
set output $expect_out(buffer)
puts "$output"
}
'
输出:
spawn telnet 172.23.149.139 2033
can't read "expect_out(buffer)": no such variable
while executing
"expect {
Prompt> { send \"dir\r\" }
set output $expect_out(buffer)
puts "$output"
}
"
我根据建议将其更改为。但我仍然面临错误。
脚本:
output=$(expect -c '
spawn telnet '"$IP $PORT1"'
sleep 1
send '"\r"'
send '"\r"'
expect Prompt> { send '"dir\r"' }
expect '"\n"'
expect -indices Prompt>
puts '"[string range $expect_out(buffer) 0 [expr $expect_out(0,end) - 1]]"'
')
echo "======="
echo "$output"
echo "======="
输出:
syntax error in expression "(0,end) - 1"
while executing
"expr (0,end) - 1"
invoked from within
"string range (buffer) 0 [expr (0,end) - 1]"
invoked from within
"puts [string range (buffer) 0 [expr (0,end) - 1]]"
=======
spawn telnet 1.1.1.1 2000
Trying 1.1.1.1...
Connected to 1.1.1.1 (1.1.1.1).
Escape character is '^]'.
Prompt>
Prompt>
=======
因此,为了避免该错误,我将该行更改
puts '"[string range $expect_out(buffer) 0 [expr $expect_out(0,end) - 1]]"'
为
puts '"$expect_out(buffer)"'
但随后我没有收到任何错误,但 dir
的输出也没有被打印。像这样的东西:
Prompt>
Prompt> (buffer)
I am trying to capture the output of the "dir" command by logging into a switch, but I am unable to do so. I am using Expect within Bash. I am making use of expect_out to capture output of that command in a buffer and print it out. Actually I want to capture the output and perform some operations on it.
Script:
#!/bin/bash
expect -c "
spawn telnet 1.1.1.1 2000
sleep 1
send \"\r\"
send \"\r\"
expect {
Prompt> { send \"dir\r\" }
}
set output $expect_out(buffer)
"
echo "$output"
Output:
spawn telnet 1.1.1.1 2000
Trying 1.1.1.1...
Connected to 1.1.1.1 (1.1.1.1).
Escape character is '^]'.
Prompt>
Prompt>
After these prompts are displayed, the scripts just exits. How can I fix this problem?
After I split it, I can use parameter substitution as well as single quotes. Now I am facing different error.
Script:
expect -c "
spawn telnet $IP $PORT1
sleep 1
send \"\r\"
send \"\r\"
"
expect -c '
expect {
Prompt> { send \"dir\r\" }
set output $expect_out(buffer)
puts "$output"
}
'
Output:
spawn telnet 172.23.149.139 2033
can't read "expect_out(buffer)": no such variable
while executing
"expect {
Prompt> { send \"dir\r\" }
set output $expect_out(buffer)
puts "$output"
}
"
I changed it to according to the suggestions. But I am still facing errors.
Script:
output=$(expect -c '
spawn telnet '"$IP $PORT1"'
sleep 1
send '"\r"'
send '"\r"'
expect Prompt> { send '"dir\r"' }
expect '"\n"'
expect -indices Prompt>
puts '"[string range $expect_out(buffer) 0 [expr $expect_out(0,end) - 1]]"'
')
echo "======="
echo "$output"
echo "======="
Output:
syntax error in expression "(0,end) - 1"
while executing
"expr (0,end) - 1"
invoked from within
"string range (buffer) 0 [expr (0,end) - 1]"
invoked from within
"puts [string range (buffer) 0 [expr (0,end) - 1]]"
=======
spawn telnet 1.1.1.1 2000
Trying 1.1.1.1...
Connected to 1.1.1.1 (1.1.1.1).
Escape character is '^]'.
Prompt>
Prompt>
=======
Hence to circumvent the error, I changed, the line
puts '"[string range $expect_out(buffer) 0 [expr $expect_out(0,end) - 1]]"'
to
puts '"$expect_out(buffer)"'
But then I am getting no error, but the output of dir
is also not getting printed. Something like:
Prompt>
Prompt> (buffer)
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
第二个“拆分”Expect 程序无权访问生成的 telnet 进程。当您像这样拆分它们时,您使它们成为独立的(一个无法访问另一个的变量或状态;实际上,当第二个启动第一个及其telnet进程时,没有不再存在)。
shell 将自动连接任何字符串(未用未加引号/未转义的空格分隔),而不考虑它们使用的引号类型(如果有)。这意味着您可以开始将 Expect 程序的第一部分放在单引号中,切换到双引号进行参数替换,然后返回到程序其余部分的单引号(以避免必须转义任何
"$\`
出现在您的 Expect 代码中)。它使用单引号来保护大部分程序,但切换回双引号以使 shell 将其 HOST 和 IP 参数替换为 Expect 的文本 接下来,启动 expect 的 shell 无法访问 Expect 程序内的变量集。从子进程
收集输出的正常方法是让它写入 stdout 或 stderr,然后让 shell 收集。通过命令替换(
$()
)的输出,您可以使用
puts
将字符串发送到 stdout。还将向标准输出发送正常的“交互”输出(它从任何生成的命令接收到的内容以及发送给它们的内容;即,如果您手动运行生成的命令,您会看到什么)。您可以使用log_user 0
禁用此默认日志记录。你可以这样写你的程序:
The second of your “split” Expect programs does not have access to the spawned telnet process. When you split them like that, you made them independent (one can not access the variables or state of the other; actually by the time the second one has started the first one, and its telnet process, no longer exist).
The shell will automatically concatenate any strings (that are not separated by unquoted/unescaped whitespace) without regard to the kind of quotes (if any) they use. This means you can start put the first part of your Expect program in single quotes, switch to double quotes for the parameter substitution, and then go back to single quotes for the rest of the program (to avoid having to escape any of
"$\`
that occur in your Expect code).It uses single quotes to protect most of the program, but switches back to double quotes to let the shell substitute the its HOST and IP parameters into the text of the Expect program.
Next, the shell that started expect can not access variable set inside the Expect program. The normal way to collect output from a child process is to have it write to stdout or stderr and have the shell collect the output via a command substitution (
$()
).In Tcl (and Expect), you can use
puts
to send a string to stdout. But, by default, Expect will also send to stdout the normal “interaction” output (what it receives from any spawned commands and what it sent to them; i.e. what you would see if you were running the spawned command manually). You can disable this default logging withlog_user 0
.You might write your program like this:
由于您的 Expect 脚本用双引号括起来,因此 shell 会将
$expect_out
扩展为空字符串。将期望脚本的主体放在单引号中。当您在 Expect 中设置变量时,shell 将不知道。当 Expect 脚本完成时,它的变量也会消失。您必须
放入
expect_out 缓冲区。Because your Expect script is enclosed in double quotes, the shell is expanding
$expect_out
to an empty string. Put the body of the expect script in single quotes.When you set a variable in Expect, the shell will have no idea. When the Expect script completes, its variables vanish too. You have to
puts
the expect_out buffer.