我正在用bash写一些期望命令。
脚本:
#!/bin/bash
set timeout -1
expect -c "
spawn telnet $IP $PORT1
sleep 1
send \"\r\"
send \"\r\"
expect Prompt1>
interact timeout 20 {
sleep 1
}
expect {
Prompt2> {send \"dir\r\" }
}
"
我使用脚本的目的是,首先让它远程登录到计算机,当它看到Prompt1时,让它提供控制权,我将执行命令以加载特定的图像。然后等待,直到Prompt2出现(表明图像已加载)。然后让它执行其他命令集。
运行脚本后,我可以进入交互模式,加载我的图像。问题是退出远程计算机上的交互模式,并将控制权交还给它。
我得到的错误:
expect: spawn id exp4 not open
while executing
"expect -nobrace Prompt2 {send "dir\r" }"
invoked from within
"expect {
Prompt2 {send "dir\r" }
}"
我该怎么做?
return
进行交互,并提供某种方式来知道您已释放控制权...在这种情况下,我使用三个加号并按Enter。\r
。我编辑了我认为您要尝试执行的操作...示例如下...
#!/bin/bash
set timeout -1
expect -c "
spawn telnet $IP $PORT1
sleep 1
send \"\r\"
send \"\r\"
expect Prompt1>
interact +++ return
send \"\r\"
expect {
Prompt2> {send \"dir\r\" }
}
"
更改的代码:
expect Prompt1>
interact timeout 10 return
expect {
timeout {exp_continue}
Prompt2 {send \"dir\r\" }
}
超时10的值与我们最初设置的set timeout -1
不相关。因此,我可以在Prompt1
上执行所需的任何命令,一旦键盘空闲10秒钟,脚本就会重新获得控制权。甚至在此之后,我又遇到了一个问题,在
Prompt1
之后,我想执行命令以加载特定的图像。图像加载大约需要2分钟。即使使用set timeout -1
,脚本也会等待Prompt2
超时。我证实这甚至不是telnet超时。但是解决方案是在expected语句中添加超时情况下的exp_continue。为了使您的
set timeout -1
生效,应将其放置在期望值中的spawn telnet命令之前。
return
不适用于我,因为就我而言,这不是一个可以简单地再次提示我相同问题的外壳程序。在执行return
之前,我不知道如何使它与打印的内容相匹配。expect_out(用于解决上述问题)=失败
Upon matching a pattern (or eof or full_buffer), any matching and previously unmatched output is saved in the variable expect_out(buffer).
但是我无法使它正常工作(除非我在下面使用过它,再加上-indices
使它在那里工作,而且不知道如何使它工作以将先前的输出馈送到新的expect { ... }
块中。)expect_user
并且使用here的解决方案
expect_user
对我也不起作用,因为它没有解释,也没有使用我想要的方式,因此也不知道如何在我的实际期望文件中应用这个有限的示例。我的解决方案
因此,我要做的是避免使用交互模式,而只是有一种提供输入的方法,一次只能一行。它甚至适用于箭头键和
alt+...
(在dpkg对话框问题中),但有时不适用于简单的<enter>
(对于dpkg对话框中的<Yes>
命中alt + y或<Ok>
的alt + o)。 (有人知道如何发送回车吗?不是'\ n',而是像dpkg Dialog这样的回车键吗?)
-i $user_spawn_id
部分意味着,它不仅查看用户的生成过程,还查看用户键入的内容。这会影响其后的所有内容,因此您可以使用expect_after
或将其置于其余的下方,而不是expect_before
。-indices
使得可以读取匹配的正则表达式的捕获部分。expect_out(1,string)
是我想要的部分(冒号除外)。
expect_after { -i $user_spawn_id # single line custom input; prefix with : and the rest is sent to the application -indices -re ":(.*)" { send "$expect_out(1,string)" } }
使用expect_after
表示它将应用于所有随后的expect
块,直到下一个expect_after
为止。因此,您可以将其放在文件中通常expect
行的上方。和我的案情/目的
我想自动执行do-release-upgrade,它不能正确支持通常的Debian非交互式标志(请参见here)...它只是挂起并忽略输入,而不是在出现问题后继续进行。但是问题是无法预料的……升级失败意味着您可能会弄乱系统,因此需要回退到交互。