2017-06-17 63 views
2

編輯:我已經通過引用Exploring Expect書來解決它。但請不要猶豫,添加我的答案或提出其他建議,但!當我被允許時(從現在起2天),我會將其標記爲回答。如何在TCL Expect中的多個過程之間共享衍生的SSH過程?

我環顧四周,很遺憾,我無法在本網站上使用SSH期望過多。我對Expect相對來說比較陌生,但我一直在用Exploring Expect這本書教我自己。

我的問題是:如何爲多個tcl程序使用單個衍生的SSH進程?我現在的解決方法是在程序1結束時關閉SSH連接,並在程序2中重新生成一個新的SSH連接。

示例:(該示例簡化了很多步驟,僅包含必要的組件我的問題...我的整個計劃是200線,截至目前)

;# Proc definition for procedure1 
    proc procedure1 {user host pw} { 
    spawn /usr/bin/ssh [email protected]$host 
    expect "Password:" 
    send "$pw\r" 
    expect "#" ;# This is my device's prompt 
    ;# From here it does a bunch of stuff... sends commands to the SSH 
    ;# session, captures output, builds arrays and lists, etc 
    send "exit" ;# Disconnects the SSH session 
    return $mylist ;# returns a list of numbers to be used in procedure 2 
    } 

;# Proc definition for procedure2 
    proc procedure2 {resultofproc1 user host pw} {  
    spawn /usr/bin/ssh [email protected]$host 
    expect "Password:" 
    send "$pw\r" 
    expect "#" ;# This is my device's prompt 
    ;# Proc 2 now continues on in the same device using the results (a 
    ;# list) from proc1. 
    return 
    } 



    ;# Procedure call for first procedure: 
    set resultofproc1 "[procedure1 $user $host $pw]" 

    ;# Procedure call for second procedure: 
    procedure2 $resultofproc1 $user $host $pw 

,而不是關閉在程序1月底的SSH連接,並在重新開放的過程2開頭的SSH連接,我怎麼能發送命令從procedure2到在procedure1中打開的SSH連接?很明顯,我將不得不刪除發送出口,以保持連接打開。假設這是可能的...這是一個很好的做法,還是我最好分離程序之間的連接?如果是這樣,你可以修改我的代碼示例來演示如何?

從我收集的,我認爲它與spawn_id變量..但我不知道如何在我的代碼中實現。我目前正在閱讀探索期望書中的第10章「處理多個進程」。如果我可以自行解決,我會報告回來。

感謝您的協助!

我已經查看了這些答案在計算器:

Tcl Expect Keep SSH Spawn open

Expect Procedure for SSH Login

Using procedure for spawing SSH doesn't work properly with expect

回答

0

啊,我是如此接近!如果我在「探索期望書」中再花幾分鐘時間,我會想清楚的。無論如何,這是我的解決方案。希望它可以幫助其他人解決同樣的問題。

它與spawn_id變量有關。基本上,默認情況下,send和expect命令只與最後產生的進程交互。每個產生的進程都被賦予一個唯一的spawn_id值。您可以將過程的spawn_id設置爲另一個衍生進程的spawn_id。

下面是修改以支持spawn_id在變量在我原來的問題代碼:

;# Proc definition for procedure1 
    proc procedure1 {user host pw} { 
    spawn /usr/bin/ssh [email protected]$host 
    global procedure1_spawnid   ;# Creates a global variable called 
             ;# procedure1_spawnid 
    set procedure1_spawnid $spawn_id ;# Assigns the spawn_id of the SSH process to the 
             ;# global variable. 
    expect "Password:" 
    send "$pw\r" 
    expect "#" ;# This is my device's prompt 
    ;# From here it does a bunch of stuff... sends commands to the SSH 
    ;# session, captures output, builds arrays and lists, etc 
    return $mylist ;# returns a list of numbers to be used in procedure 2 
    } 

;# Proc definition for procedure2 
    proc procedure2 {resultofproc1} {  
    global procedure1_spawnid 
    set spawn_id $procedure1_spawnid ;# Sets the spawn_id to that of the SSH connection 
             ;# in procedure1. 
    send "show ip interface brief" 
    expect "#" 
    ;# The show ip interface brief command is sent to the device through the 
    ;# SSH connection opened in procedure1. 
    return 
    } 



    ;# Procedure call for first procedure: 
    set resultofproc1 "[procedure1 $user $host $pw]" 

    ;# Procedure call for second procedure: 
    procedure2 $resultofproc1 

更多信息可以在探索期待可以發現,233

如果任何人有任何建議或改進頁面,請隨時把它們放在我身上!我仍然在學習tcl/expect。

2

您可以使用global來聲明spawn_id作爲全局變量。據預計手冊:

CAVEATS

...
期待需要作用域的一個相當自由的觀點。特別是,通過特定於期望程序的命令讀取的變量將首先從本地範圍尋求,並且如果未找到,則在全局範圍中。例如,這可避免在您使用expect編寫的每個過程中放置​​global timeout。另一方面,寫入的變量始終在本地範圍內(除非已發出global命令)。這導致最常見的問題是在過程中執行spawn。在程序之外,spawn_id不再存在,所以產生的過程不再僅僅因爲作用域而被訪問。添加一個global spawn_id到這樣的程序。
...


您也可以利用Tcl的upvar命令。例如:

[STEP 101] $ cat foo.exp 
proc expect_prompt {} { 
    upvar spawn_id spawn_id 
    expect -re {bash-[.0-9]+[#$] $} 
} 

proc open_conn {} { 
    upvar spawn_id spawn_id 
    spawn bash --noprofile --norc 
    expect_prompt 
} 

proc close_conn {} { 
    upvar spawn_id spawn_id 
    send "exit\r" 
    expect eof 
} 

proc send_cmd { cmd } { 
    upvar spawn_id spawn_id 
    send "$cmd\r" 
    expect_prompt 
} 

proc main {} { 
    open_conn 

    send_cmd "echo spawn_id=$spawn_id" 
    send_cmd "ps Tu" 

    close_conn 
} 

main 
[STEP 102] $ 

輸出:

[STEP 103] $ expect foo.exp 
spawn bash --noprofile --norc 
bash-4.4$ echo spawn_id=exp6 
spawn_id=exp6 
bash-4.4$ ps Tu 
USER  PID %CPU %MEM  VSZ RSS TT STAT STARTED  TIME COMMAND 
root 71513 0.0 0.0 2433012 788 s013 R+ 12:58PM 0:00.00 ps Tu 
pynexj 71510 0.0 0.0 2445360 1572 s013 Ss 12:58PM 0:00.01 bash --noprofile --norc 
bash-4.4$ exit 
exit 
[STEP 104] $ 
+0

感謝whjm!我將更多地關注upvar與全球變量的想法。 – David00

+0

手冊中提取的內容意味着你只需要在'open_conn'進程中使用'global spawn_id',你可以從所有其他helper procs中移除'upvar'命令。他們將自動從全局範圍獲取spawn_id。這個例外是在'main' proc中,你明確引用了var:那裏,你可以使用'$ :: spawn_id'從全局範圍中獲取它。 –

+0

@glennjackman - 我同意'全球'是足夠的,更容易對大多數情況下。處理多個spawn或編寫庫代碼時,'upvar'更好。 – pynexj

相關問題