Bash 脚本中的 Expect:expect_out 不打印缓冲区

发布于 2024-10-31 06:15:37 字数 2339 浏览 4 评论 0原文

我试图通过登录交换机来捕获“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 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

花桑 2024-11-07 06:15:37

第二个“拆分”Expect 程序无权访问生成的 telnet 进程。当您像这样拆分它们时,您使它们成为独立的(一个无法访问另一个的变量或状态;实际上,当第二个启动第一个及其telnet进程时,没有不再存在)。


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

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

它使用单引号来保护大部分程序,但切换回双引号以使 shell 将其 HOST 和 IP 参数替换为 Expect 的文本 接下来,启动 expect 的 shell 无法访问 Expect 程序内的变量集。从子进程


收集输出的正常方法是让它写入 stdout 或 stderr,然后让 shell 收集。通过命令替换($())的输出

,您可以使用 puts 将字符串发送到 stdout。还将向标准输出发送正常的“交互”输出(它从任何生成的命令接收到的内容以及发送给它们的内容;即,如果您手动运行生成的命令,您会看到什么)。您可以使用 log_user 0 禁用此默认日志记录。

你可以这样写你的程序:

#!/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 "======="

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).

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.


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 with 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 "======="
妄司 2024-11-07 06:15:37

由于您的 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.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文