2010-12-20 41 views
0

我有我需要安裝我的公鑰的主機列表。爲此,我編寫了一個ruby腳本,它調用期望腳本並將密碼,主機名和公鑰文件傳遞給它。這個expect文件依次爲每個主機執行ssh-copy-id,通過輸入密碼並回答未知主機密鑰的「yes」。期望腳本凍結從Ruby調用時

預期腳本在命令行運行時絕對正常。但是,當從一個ruby腳本執行時,期望對未知的主機密鑰確認回答「是」:「您確定要繼續連接(是/否)?」。期望腳本只在「是/否」問題被拋出時凍結。

任何幫助將不勝感激。

這裏是我的Ruby腳本:

#!/usr/bin/env ruby -w 

hosts=['[email protected]','[email protected]','[email protected]'] 
password="blahblahblah" 
key_file="/home/blah/.ssh/id_rsa.pub" 

hosts.each{ |host| 
    command="expect sshcopy.exp #{host} #{key_file} #{password}" 
    `#{command}` 
} 

這裏是我期待的腳本sshcopy.exp

set host [lrange $argv 0 0] 
set key_file [lrange $argv 1 1] 
set password [lrange $argv 2 2] 
spawn ssh-copy-id -i $key_file $host 
expect -nocase "*password: $" {send "$password\r"; interact} -nocase "*are you sure you want to continue connecting (yes/no)? $" {send "yes\r"} eof{exit} 
expect -nocase "*password: $" {send "$password\r"; interact} eof{exit} 

您將看到兩個期望上述聲明。第一個語句處理立即通過交互立即詢問密碼(即主密鑰已知)的情況。它還通過回答「是」來處理識別出未知主機的情況。

當第一個期望回答「是」導致密碼被問到時,第二個expect語句被執行。

+0

在您期望的腳本中,使用具有單個索引的'lindex'而不是'lrange'。否則,如果任何參數包含Tcl列表元字符(例如空格或花括號),則可以獲得「驚喜」;這些東西在文件名和密碼中相對可能... – 2010-12-23 11:58:47

+1

另外,在命令行上傳遞密碼是不安全的。 'ps'命令(帶有正確的參數)可以讀取系統中任何進程的完整參數。與環境變量相同(儘管需要一個不同的選項來獲取它們)。安全的方式是通過stdin管道發送它,或者將它放在帶有嚴格權限的文件*中,並在命令行中傳遞該文件的名稱(因爲知道文件名並不能幫助黑客讀取它) )。但是,如果你在一個可以保證沒有入侵者的系統上(很棘手!),保證安全並不重要。 – 2010-12-23 12:02:08

回答

1

我想象的問題是,您可以通過`backticks`調用期望腳本,但expect腳本會相互影響。似乎ruby反引號不允許完全交互(可能阻止stdin)。您可能需要調查ruby的期望模塊,並取消單獨的期望腳本。

0

謝謝你們。但我發現,這個問題的答案很簡單:

puts `#{command}` 

我認爲``在紅寶石將與Ruby腳本合併shell命令的輸出和錯誤句柄。這是錯誤的。