2013-03-11 66 views
1

“互动”不起作用我正在构建一个简单的ssh登录包装工具来帮助自动登录到许多服务器的地狱之一。
它首先从用户输入中获取描述,然后提取安全地存储在某个地方的相应(最相关的)服务器IP和密码,使用它创建一段期望脚本。期望脚本内容传输到

的期望脚本看起来是这样的:

 
    spawn ssh2 -q -t [email protected] 
    expect { 
     "assword:" {send "Bob123\r"} 
    } 
    interact 

当我管这个预期(预期可从标准输入读取脚本)一切 顺利,直到达到“互动” 预计声称,它接收eof和 立即终止,然后我将它存储到一个文件中,说tmp.exp同样的问题 发生在我“预计< tmp.exp”时,但是当我执行“expect -f tmp.exp” 一切正常。

我认为原因是“互动”从fd0获取输入,通过我的程序(或shell)重定向到管道。 这是否意味着当我做 如“expect < xx.exp”时,我不能使用交互? 有没有办法在“交互”命令之前恢复fd0到真实终端? 我搜索了很多,我得到的只是'close_on_eof 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或根本没有开始。

+0

这确实有效!然而,一些终端的属性似乎混乱了。例如,当我以这种方式登录到另一台服务器并删除空格时,它会打印一个'^ H'符号而不是删除最后一个字符。并输入“退出”不会退出会话。本地文件版本一切正常,我想我不想再去处理终端。 – user1206899 2013-03-30 09:21:29

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 
$