简体   繁体   English

在 Bash 脚本中期望:expect_out 不打印出缓冲区

[英]Expect in Bash script: expect_out not printing out buffer

I am trying to capture the output of the "dir" command by logging into a switch, but I am unable to do so.我试图通过登录交换机来捕获“dir”命令的输出,但我无法这样做。 I am using Expect within Bash.我在 Bash 中使用 Expect。 I am making use of expect_out to capture output of that command in a buffer and print it out.我正在使用 expect_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.但是后来我没有收到任何错误,但是dir的输出也没有被打印出来。 Something like:就像是:

Prompt>

Prompt> (buffer)

The second of your “split” Expect programs does not have access to the spawned telnet process.您的第二个“拆分”Expect 程序无权访问生成的telnet进程。 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).当你像这样拆分它们时,你使它们独立(一个不能访问另一个的变量或状态;实际上当第二个启动第一个时,它的telnet进程不再存在)。


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. shell 将自动连接任何字符串(未被未加引号/未转义的空格分隔),而不考虑它们使用的引号类型(如果有)。 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).这意味着您可以开始将 Expect 程序的第一部分放在单引号中,切换到双引号以替换参数,然后返回到程序其余部分的单引号(以避免必须转义任何"$\`出现在您的 Expect 代码中)。

expect -c '
spawn telnet '"$HOST $PORT"'
sleep 1
⋮ (rest of Expect program)
'

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.它使用单引号来保护大部分程序,但切换回双引号让 shell 将其 HOST 和 IP 参数替换为 Expect 程序的文本。


Next, the shell that started expect can not access variable set inside the Expect program.其次,启动expect的shell 无法访问Expect 程序内部的变量集。 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 ( $() ).从子进程收集输出的正常方法是让它写入 stdout 或 stderr,并让 shell 通过命令替换 ( $() ) 收集输出。

In Tcl (and Expect), you can use puts to send a string to stdout.在 Tcl(和 Expect)中,您可以使用puts将字符串发送到 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; ie what you would see if you were running the spawned command manually).但是,默认情况下,Expect 还将向 stdout 发送正常的“交互”输出(它从任何生成的命令接收的内容以及它发送给它们的内容;即,如果您手动运行生成的命令,您会看到什么)。 You can disable this default logging with log_user 0 .您可以使用log_user 0禁用此默认日志记录。

You might write your program like this:你可以这样写你的程序:

#!/bin/sh
output=$(expect -c '
# suppress the display of the process interaction
log_user 0

spawn telnet '"$HOST $PORT"'
sleep 1
send "\r"
send "\r"
# after a prompt, send the interesting command
expect Prompt> { send "dir\r"  }
# eat the \n the remote end sent after we sent our \r
expect "\n"
# wait for the next prompt, saving its position in expect_out(buffer)
expect -indices Prompt>

# output what came after the command and before the next prompt
# (i.e. the output of the "dir" command)
puts [string range $expect_out(buffer) \
                   0 [expr $expect_out(0,start) - 1]]
')
echo "======="
echo "$output"
echo "======="

Because your Expect script is enclosed in double quotes, the shell is expanding $expect_out to an empty string.因为您的 Expect 脚本包含在双引号中,所以 shell 将$expect_out扩展为空字符串。 Put the body of the expect script in single quotes.将期望脚本的主体放在单引号中。

When you set a variable in Expect, the shell will have no idea.当您在 Expect 中设置一个变量时,shell 将不知道。 When the Expect script completes, its variables vanish too.当 Expect 脚本完成时,它的变量也会消失。 You have to puts the expect_out buffer.您必须puts expect_out 缓冲区。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM