web-dev-qa-db-ja.com

スクリプトを期待する+送信文字列を逃すことを期待する+遅延の問題

一部のSolarisマシンに自動的にログインし、hostnameコマンドを実行するために(expectに基づいて)active.kshスクリプトを記述します(どのホスト名がアクティブマシンであるかを確認するために仮想IPにログインします-2つのクラスタソラリスマシンがあります)

問題はexpectにあります。 expectはパスワード文字列(pass123)を送信し、Passwordの質問を逃し、パスワードを待ちます。

したがって、実際にはパスワード(pass123)はパスワードの質問の後に入力されました。ほとんどの場合、expectスクリプトは正常に機能しますが、パスワードが欠落することもあります。

問題の例

 ./active.ksh
 spawn ssh 10.10.18.61
 sh: /usr/local/bin/stty: not found
 This computer system, including all related equipment, networks and network devices      (specifically including Internet access),is provided only for authorized uss
 Password:        * my remark - pass123 string was missed the Password Question        pass123
 Password: 

スクリプト

  #!/bin/ksh

  VIP_ADDRESS=10.10.18.61


  expect_for_verify_which_active_machine=`cat << EOF
  set timeout -1
  spawn  ssh   $VIP_ADDRESS 
  expect {
  ")?"   { send "yes\r"  ; exp_continue  }
  Password:  {send "pass123\r"}
  }
  expect >  {send "hostname\r"}
  expect >    {send exit\r}
  expect eof
  EOF`


  expect -c  "$expect_for_verify_which_active_machine"

正しい結果の例

  ./active.ksh 
  [Friday, February 24, 2012  2:32:06 PM IST] INFO Verify which is active SMU machine 
  spawn ssh 10.10.18.61
  sh: /usr/local/bin/stty: not found
  This computer system, including all related equipment, networks and network devices       (specifically including Internet access),is provided only for authorized uss
  yes
  Password: 
  Last login: Fri Feb 24 14:32:06 2012 from smu1a
  This computer system, including all related equipment, networks and network devices       (specifically including Internet access),is provided only for authorized uss
  solaris1:/ ROOT > hostname
  solaris1
  solaris1:/ ROOT > exit

  logout
  Connection to 10.10.18.61  closed.
7
Eytan

ログイン時に文字列を監視する場合、「パスワード:」の使用は避けたいでしょう。大文字になっているとは限りません。

期待を-re "(.*)assword:"または"assword:"に変更すると、ラインをキャッチするのにはるかに効果的です。

それでもタイミングが速すぎる場合は、スリープ1にできます。送る前に

これは私が期待するものです

expect {
    "(yes/no)?" { send "yes\n" }
    "passphrase" { send "\r" }
    -re "(.*)assword:"  { sleep 1; send -- "password\r" }
    -re $Prompt { return }
    timeout     { puts "un-able to login: timeout\n"; return }
    eof         { puts "Closed\n" ; return }
}
7
Xarses

expectを使用している理由がはっきりしません。リモートホストへのsshアクセスがあるので、最も簡単な解決策は、この目的のためにssh public key authentication を明示的に確立することです。その後、単に実行することができます...

ssh 10.10.18.61 hostname

...そしてすべてがうまくいく*。 expectを使用していても、パスワード認証を使用しても上記のコマンドを発行でき、expectを使用してリモートシェルと対話することを心配する必要がないため、作業が多すぎます。あなたは次のようなものを送るでしょう:

#!/bin/sh

VIP_ADDRESS=10.10.18.61

expect <<EOF
spawn ssh $VIP_ADDRESS hostname
expect Password:
send "pass123\n"
expect eof
EOF

以上です。

-dフラグを使用して、expectスクリプトをデバッグできます。私の場合、デバッグモードで実行された上記のexpectスクリプトの出力には、次のものが含まれます。

expect: does "" (spawn_id exp4) match glob pattern "password:"? no
lars@localhost's password: 
expect: does "lars@localhost's password: " (spawn_id exp4) match glob pattern "password:"? yes
expect: set expect_out(0,string) "password:"
expect: set expect_out(spawn_id) "exp4"
expect: set expect_out(buffer) "lars@localhost's password:"
send: sending "PASSWORD\n" to { exp4 }

myhost.example.com
expect: read eof
expect: set expect_out(spawn_id) "exp4"
expect: set expect_out(buffer) " \r\nobliquity.int.seas.harvard.edu\r\n"

これは、expectが何と一致し、何を送信しているかを正確に示します。

*技術的には、いくつかのホストキーの問題を解決する必要があるかもしれませんが、これは簡単です。

4
larsks