2010-12-20 7 views
0

公開鍵をインストールする必要のあるホストのリストがあります。この目的のために、私はexpectスクリプトを呼び出してパスワード、ホスト名と公開鍵ファイルを渡すrubyスクリプトを作成しました。このexpectスクリプトは、パスワードを入力し、未知のホスト鍵に対して "yes"と答えて、各ホストにssh-copy-idを実行します。Rubyから呼び出されるとスクリプトが凍結する

expectスクリプトは、コマンドラインで実行するときれいに動作します。しかし、ルビスクリプトから実行すると、未知のホスト鍵確認のために "yes"と答えることができません: "あなたは接続を続行してもよろしいですか?" expectスクリプトは、yes/noの質問がスローされたときにフリーズします。

ご協力いただきますようお願い申し上げます。ここで

は私のRubyスクリプトです:あなたは、2つの上記の文を期待するでしょう

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} 

#!/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を期待しています。最初のステートメントは、パスワードがすぐに尋ねられる(すなわち、ホストキーが知られている)場合、によって対話する場合を即座に処理する。。また、「はい」と答えることで、未知のホストが識別された場合も処理します。

2番目のexpect文は、最初のexpectが "yes"と応答してパスワードが要求されたときに実行されます。

+0

あなたのexpectスクリプトでは、2つの 'lrange'の代わりに1つのインデックスで' lindex'を使います。さもなければ、引数にTclリストのメタキャラクター(例えば、スペースや中括弧)が含まれていると "驚き"を得ることができます。これらのことは、ファイル名とパスワードで比較的可能性があります。 –

+1

また、コマンドラインでのパスワードの受け渡しは安全ではありません。 'ps'コマンド(正しい引数を指定する)は、システム上のどのプロセスにも完全な引数を読み込むことができます。環境変数と同じです(しかし、それらを得るには別のオプションが必要です)。安全な方法は、stdinパイプ上で送信するか、厳密なアクセス権を持つファイル*に入れ、コマンドラインでそのファイルの名前を渡すことです(ファイル名がハッカーの読み込みに役立たないため)。しかし、あなたが侵入者がいないことを保証できるシステム(トリッキーなシステム)を利用しているなら、安全であることはあまり重要ではありません。 –

答えて

1

私は、expectスクリプトを`backticks`と呼んでいるが、expectスクリプトがやりとりするというのが問題だと思います。ルビーのバッククォートは、完全な相互作用(おそらくstdinをブロック)を許可していないようです。 Rubyのexpectモジュールを調べて、別のexpectスクリプトを削除することができます。

0

ありがとうございます。しかし、私はこの問題への答えは非常にシンプルであることが判明:

puts `#{command}` 

私は `` RubyでRubyスクリプトでシェルコマンドのstdoutとstderrハンドルをマージすると仮定しました。これは間違っています。

関連する問題