質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

ただいまの
回答率

90.21%

Expectのパスワード受け渡しができない

解決済

回答 1

投稿 編集

  • 評価
  • クリップ 0
  • VIEW 3,091

minhouse10

score 33

あるLinuxサーバーから、Expectコマンドを利用して複数台ある他のLinuxサーバーのIPアドレスをwhileで読み込ませて、順番にSCPコマンド自動化スクリプトを作成しておりますが、パスワード入力のプロンプトでどうしても処理がストップしてしまいます。どうもsendコマンドによるパスワード受け渡しがうまくできていないようです。

現象:以下パスワード入力プロンプトで止まってしまう

spawn scp test.txt ohm@192.168.38.194:/tmp
ohm@192.168.38.194's password:

フルコードは以下になります。どなたかご教授、アドバイス頂けますでしょうか?

#!/bin/bash

ip_file='systems.txt'
USER='ohm'
PASS='#!8102L#>t'
TARGET_DIR='test.txt'
CR_DIR='/tmp/'

while read line || [ -n "${line}" ];
do
    expect -c "
    set timeout -1
    spawn scp ${TARGET_DIR} ${USER}@${line}:${CR_DIR}

    expect {
      \" Are you sure you want to continue connecting (yes/no)? \" {
        send \"yes\r\"
        expect \"${USER}@${line}'s password: \"
        send \"${PASS}\r\"
       }
       exp_continue
    }
    interact
"
done < ${ip_file

修正箇所

コードを以下の様に変更した結果、パスワードプロンプトで停止せずスクリプトの実行は終了たが、scpの処理が実行されない。

    expect {
      \" Are you sure you want to continue connecting (yes/no)? \" {
        send \"yes\r\"
        expect \"${USER}@${line}'s password:\"
        -re \"${USER}@${line}'s password:\"
        send \"${PASS}\r\"
    } -re \"${USER}@${line}'s password:\" {
        send \"${PASS}\r\"
    }
    interact
        "


scp -vオプションを付けて実行した結果になります。scpコマンドは実行されている事が確認。
[root@host]# bash scp_auto.sh
spawn scp -v test.txt ohm@22.222.22.222:/tmp
Executing: program /usr/bin/ssh host 22.222.22.222, user far, command scp -v -t /tmp
OpenSSH_6.6.1, OpenSSL 1.0.1e-fips 11 Feb 2013
debug1: Reading configuration data /etc/ssh/ssh_config
debug1: /etc/ssh/ssh_config line 56: Applying options for *
debug1: Connecting to 22.222.22.222 [22.222.22.222] port 22.
debug1: Connection established.
debug1: permanently_set_uid: 0/0
debug1: identity file /root/.ssh/id_rsa type -1
debug1: identity file /root/.ssh/id_rsa-cert type -1
debug1: identity file /root/.ssh/id_dsa type -1
debug1: identity file /root/.ssh/id_dsa-cert type -1
debug1: identity file /root/.ssh/id_ecdsa type -1
debug1: identity file /root/.ssh/id_ecdsa-cert type -1
debug1: identity file /root/.ssh/id_ed25519 type -1
debug1: identity file /root/.ssh/id_ed25519-cert type -1
debug1: Enabling compatibility mode for protocol 2.0
debug1: Local version string SSH-2.0-OpenSSH_6.6.1
debug1: Remote protocol version 2.0, remote software version OpenSSH_7.2
debug1: match: OpenSSH_7.2 pat OpenSSH* compat 0x04000000
debug1: SSH2_MSG_KEXINIT sent
debug1: SSH2_MSG_KEXINIT received
debug1: kex: server->client aes128-ctr hmac-sha1 none
debug1: kex: client->server aes128-ctr hmac-sha1 none
debug1: kex: curve25519-sha256@libssh.org need=20 dh_need=20
debug1: kex: curve25519-sha256@libssh.org need=20 dh_need=20
debug1: sending SSH2_MSG_KEX_ECDH_INIT
debug1: expecting SSH2_MSG_KEX_ECDH_REPLY
debug1: Server host key: RSA c2:ae:1e:70:c4:82:7e:21:49:36:5d:4a:29:6a:2d:a9
debug1: Host '22.222.22.222' is known and matches the RSA host key.
debug1: Found key in /root/.ssh/known_hosts:18
debug1: ssh_rsa_verify: signature correct
debug1: SSH2_MSG_NEWKEYS sent
debug1: expecting SSH2_MSG_NEWKEYS
debug1: SSH2_MSG_NEWKEYS received
debug1: Roaming not allowed by server
debug1: SSH2_MSG_SERVICE_REQUEST sent
debug1: SSH2_MSG_SERVICE_ACCEPT received

debug1: Authentications that can continue: publickey,password,keyboard-interactive
debug1: Next authentication method: publickey
debug1: Trying private key: /root/.ssh/id_rsa
debug1: Trying private key: /root/.ssh/id_dsa
debug1: Trying private key: /root/.ssh/id_ecdsa
debug1: Trying private key: /root/.ssh/id_ed25519
debug1: Next authentication method: keyboard-interactive
debug1: Authentications that can continue: publickey,password,keyboard-interactive
debug1: Next authentication method: password

ohm@22.222.22.222's password: [root@host]#


修正後:
while read line || [ -n "${line}" ];
do
expect -c "
set timeout 5
spawn scp -v ${TARGET_DIR} ${USER}@${line}:${CR_DIR}
expect {
\"${USER}@${line}'s password:\"
send \"${PASS}\n\"
}
-re \"\[Pp\]assword:\" {
send \"${PASS}\n\"
}
interact
"
done < ${ip_file}

結果:
debug1: Next authentication method: password
ohm@22.222.22.222's password: usage: send [args] string
while executing
"send"
invoked from within
"expect {
"ohm@22.222.22.222's password:"
send "#!8102L#>t\n"
}"
[root@host]


修正版:成功!!

expect -c "
set timeout 5
spawn scp -v ${TARGET_DIR} ${USER}@${line}:${CR_DIR}
expect \"${USER}@${line}'s password:\" {
send \"${PASS}\n\"
}
expect \"${USER}@${line}'s password:\" {
send \"${PASS}\n\"
}
"

結果:
Sending file modes: C0755 0 test.txt
Sink: C0755 0 test.txt
test.txt                         100%    0     0.0KB/s   00:00
debug1: client_input_channel_req: channel 0 rtype exit-status reply 0
debug1: channel 0: free: client-session, nchannels 1
debug1: fd 0 clearing O_NONBLOCK
debug1: fd 1 clearing O_NONBLOCK
Transferred: sent 2688, received 4328 bytes, in 0.1 seconds
Bytes per second: sent 25747.9, received 41457.1
debug1: Exit status 0

  • 気になる質問をクリップする

    クリップした質問は、後からいつでもマイページで確認できます。

    またクリップした質問に回答があった際、通知やメールを受け取ることができます。

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

回答 1

checkベストアンサー

+1

パスワード入力プロンプトで止まるということは、expectで引っかかってないってことでしょう。
正規表現でもっと幅広くexpectしてみてはどうでしょうか。例えば

expect {
  -re \"password:\"
  send \""${PASS}\r\"
}

といった感じで。
上記のコードではコロンのあとにスペースがあるのもちょっと気になります。

(追記) expect部分、こうするとどうなるでしょう。

expect -c "
    set timeout -1
    spawn scp ${TARGET_DIR} ${USER}@${line}:${CR_DIR}

    expect {
        \"Are you sure you want to continue connecting (yes/no)? \" {
             send \"yes\r\"
             expect \"${USER}@${line}'s password: \"
             send \"${PASS}\r\"
        }
        -re \"\[Pp\]assword:\" {
            send \"${PASS}\r\"
       }
    }
   expect eof
"


-vの出力でパスワードをsendしていないので、expectあたりがちょっと変なのかも。
一段目の"Are you sure云々"のところは二回目からは出ないはずなので、外しちゃってもいいかも。

投稿

編集

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2018/03/16 15:51

    改めてありがとうございます!300台ぐらいのLinuxサーバーにSCPしなくてはならなくなったので、このスクリプトで仕事がだいぶ効率化されます^^はい、一個目を無効にするとパスワードプロンプトで停止いたします。。。

    キャンセル

  • 2018/03/16 15:53

    うーん、おかしいけど動くんならそれでいいか(www
    300台ですか。
    それだとエラー検出のロジックも入れたほうがいいかもですね。

    キャンセル

  • 2018/03/16 16:31

    ありがとうございます、はい、確かにSCPに失敗するケースも出てきそうなのでエラーロジックの適用も検討開始します。

    キャンセル

15分調べてもわからないことは、teratailで質問しよう!

  • ただいまの回答率 90.21%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる

同じタグがついた質問を見る