2013-03-11 108 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 
$