期望脚本内容通过管道输入时,“interaction”不起作用

时间:2013-03-11 14:42:07

标签: linux shell expect

我正在构建一个简单的ssh登录包装工具,以帮助自动登录到很多服务器中的一个。
它首先从用户输入中获取描述,然后提取在某处安全存储的相应(最相关)服务器IP和密码,使用它创建一个expect脚本。

expect脚本看起来像这样:

    spawn ssh2 -q -t Bob@172.23.24.35
    expect {
        "assword:" {send "Bob123\r"}
    }
    interact

当我管道这期望(期望可以从stdin读取脚本)的一切 顺利,直到达到“互动”。 期望声称它收到了eof和 立即终止。然后我把它存入一个文件说tmp.exp同样的问题 当我做“期望< tmp.exp”时会发生。但是当我执行“expect -f tmp.exp”时 一切都好。

我认为原因是“interaction”接受来自fd0的输入,fd0被我的程序(或shell)重定向到管道。 这是否意味着当我这样做时我无法使用互动 像“expect< xx.exp”这样的东西? 有没有办法在“交互”命令之前将fd0恢复到真正的终端? 我google了很多,我得到的就是'close_on_eof 0'。我找不到它的意义,也不知道它是如何运作的。提前谢谢!

2 个答案:

答案 0 :(得分:3)

我想出办法来做到这一点。见这个例子:

$ cat foo.exp
if {[catch {
    #  Close stdin and reopen it as /dev/tty. Then we are
    #+ connecting to a tty.
    close stdin
    open /dev/tty
} err]} {
    puts stderr $err
    exit 1
}

# Without this, inputed lines will be echo'ed twice.
set stty_init -echo
spawn bash --noprofile --norc

expect -re {bash-[.0-9]+(#|\$) }
interact

exit
$ expect < foo.exp
spawn bash --noprofile --norc
bash-4.2# ptree $$
705   screen -T dtterm -U
  24164 bash
    26826 expect
      26827 bash --noprofile --norc
        26830 ptree 26827
bash-4.2# exit
exit
$

为了使其更加智能,我们需要在开始时检查stdin是否是tty。

答案 1 :(得分:1)

不确定TclExpect是否提供内置方法来检查文件描述符是否为tty。我这样做了:

$ cat foo.exp
if { [catch { system {[[ -t 0 ]]} } error] } {
    puts "stdin is not a tty"
} else {
    puts "stdin is a tty"
}
$ expect foo.exp
stdin is a tty
$ expect < foo.exp
stdin is not a tty
$