2009-03-25 8 views
17

私はsshを通していくつかのルータに接続するexpectスクリプトを持っています。これらのルータはすべて同じパスワードを持っています(間違っています)、スクリプトはルータに接続できるようにパスワードを知っている必要があります。現在、パスワードはコマンドラインで引数としてスクリプトに渡されますが、これは自分の.bash_historyファイルと実行中のプロセスにそのパスワードのトレースがあることを意味します。だから代わりに、可能であれば、私はユーザーにパスワードの入力を求められるようにしたいと思います。パスワードのためのexpectスクリプトプロンプトを作成するにはどうすればよいですか?

ユーザーに期待どおりのパスワードを要求することができるかどうか知っていますか?

ありがとうございます。

編集:ルータの代わりにサーバに接続していた場合は、パスワードの代わりにsshキーを使用している可能性があります。しかし、私が使用しているルータはパスワードをサポートしています。私はそれがタイミングの問題だと思う:私は正確な理由はわからない - それはsend_userを呼び出す前stty -echoを呼び出すことが重要だと

# grab the password 
stty -echo 
send_user -- "Password for [email protected]$host: " 
expect_user -re "(.*)\n" 
send_user "\n" 
stty echo 
set pass $expect_out(1,string) 

#... later 
send -- "$pass\r" 

注:

答えて

28

使用すると、の、このようなsttyコマンドを期待しています。

は、プログラマがを読んで、すべての必要があります期待しブック:ドン・リブスによって期待探る

+2

クールありがとう!この言語がどれほど寛容でないのか驚くべきことです。「set pass $ expect_out(1、string)」と書かれました。単語 "string"の前にスペースがあり、それが爆発します。私は多くのドキュメンテーションを見つけることができません。私は期待していた以外の解決策があることを望みます。とにかく、ありがとう。 – MiniQuark

+0

"多くのドキュメントが見つかりません"一般的によく書かれていると考えられている第2版の本があります。真剣に、その本をチェックしてください。 –

+1

Re: "1"と "string"の間のスペース - Tcl(したがって期待する)には多次元配列がありません。配列キーは単なる文字列であり、 "1、string"と "1、string"は異なります。 –

6

OK、上記の2件の回答をマージ(または彼らは今ある下またはどこでも!):

#!/usr/local/bin/expect 
log_user 0 
set timeout 10 
set userid "XXXXX" 
set password "XXXXXX" 

# ############## Get two arguments - (1) Device (2) Command to be executed 
set device [lindex $argv 0] 
set command [lindex $argv 1] 

# grab the password 
stty -echo 
send_user -- "Password for [email protected]$host: " 
expect_user -re "(.*)\n" 
send_user "\n" 
stty echo 
set pass $expect_out(1,string) 

spawn /usr/local/bin/ssh -l $userid $device 
match_max [expr 32 * 1024] 

expect { 
    -re "RSA key fingerprint" {send "yes\r"} 
    timeout {puts "Host is known"} 
} 

expect { 
    -re "username: " {send "$userid\r"} 
    -re "(P|p)assword: " {send "$pass\r"} 
    -re "Warning:" {send "$pass\r"} 
    -re "Connection refused" {puts "Host error -> $expect_out(buffer)";exit} 
    -re "Connection closed" {puts "Host error -> $expect_out(buffer)";exit} 
    -re "no address.*" {puts "Host error -> $expect_out(buffer)";exit} 

    timeout {puts "Timeout error. Is device down or unreachable?? ssh_expect";exit} 
} 

expect { 
    -re "\[#>]$" {send "term len 0\r"} 
    timeout {puts "Error reading prompt -> $expect_out(buffer)";exit} 
} 


expect { 
    -re "\[#>]$" {send "$command\r"} 

    timeout {puts "Error reading prompt -> $expect_out(buffer)";exit} 
} 

expect -re "\[#>]$" 
set output $expect_out(buffer) 
send "exit\r" 
puts "$output\r\n" 

。なお、 $ password変数を$ passに変更して、他の答えと一致するようにしました。

0

また、SSH_ASKPASS環境変数を使用してX11経由でsshにパスワードを収集させることもできます。 manページから

> SSH_ASKPASS 
>  If ssh needs a passphrase, it will read the passphrase from the 
>  current terminal if it was run from a terminal. If ssh does not 
>  have a terminal associated with it but DISPLAY and SSH_ASKPASS 
>  are set, it will execute the program specified by SSH_ASKPASS 
>  and open an X11 window to read the passphrase. This is particularly 
>  useful when calling ssh from a .xsession or related script. 
>  (Note that on some machines it may be necessary to redirect the 
>  input from /dev/null to make this work.)