【linux】expectコマンドがタイムアウトしない事象 | 瀬戸内の雲のように

【linux】expectコマンドがタイムアウトしない事象

Posted: 2018-06-12


スポンサーリンク

目次

はじめに

少子高齢化・働き方改革など業務効率化の必要性が叫ばれる昨今、自動化はエンジニアにとって非常に重要なキーワードとなっています。
私のチームでも自動化は重要な課題であり、身近なところから自動化を始めています。

自動化と言えばいろいろな技術がありますが、「元祖自動化」といえばexpectコマンドを思い浮かべる人が多いのではないでしょうか。

近年よく使われるserverspec等もこの技術を使っているので、知らず知らずのうちに使っている方も多いかと思います。

今回はそんなexpectコマンドを使っていた時にうまくいかなかったことがあったのでメモしておきます。

背景

今回、あるサーバにSSHログインしてコマンドを実行するスクリプトを作りました。
その中でエラー処理として一定時間応答がない場合はタイムアウトする設定を入れていました。

しかし、実際に試してみるとこれがうまく動きません。

実際のソースコードは以下のような内容です。

#!/bin/bash
expect -c "
        # タイムアウト設定
        set timeout 10
        set default { exit 3 }

        # SSH
        spawn ssh user@192.168.0.10

        expect \"assword:\"
        send \"my_password\n\"
        expect \":~\"
        interact
"

set timeout 10で設定している通り、応答が10秒間ない場合はタイムアウトしてexit 3で抜けてほしいと思っています。

 
これをテストするため、192.168.0.10に対してのパケットをdropし、TCPコネクションが貼れないような環境を作りました。

iptables -I OUTPUT -j DROP -d 192.168.0.10 -p tcp --dport 22

これで試してみたところ、

# time sh expect_test.sh
spawn ssh user@192.168.0.10
my_password
ssh: connect to host 192.168.0.10 port 22: Connection timed out

real    2m7.239s
user    0m0.002s
sys     0m0.004s

# echo $?
0

このように、2分7秒もかかってタイムアウトし、終了コードも0になるという、全く期待通りではない動作になってしまいました。
ちなみにこの2分7秒と言うのはlinuxのTCPタイムアウトのデフォルト値なので、sshコマンドがタイムアウトしたところで終了したようです。

修正内容

調べたところ、expectの部分は条件分岐的に書くことができるらしく、今回のようなケースでは①意図した応答がある場合②応答がない場合 の2パターンを書く必要があるようです。

と言うことで以下の部分を修正しました。

修正前

        # SSH
        spawn ssh user@192.168.0.10

        expect \"assword:\"

 
修正後

        # SSH
        spawn ssh user@192.168.0.10

        # 修正箇所★★
        expect {
                default { exit 3}
                \"assword:\" { send \"my_password\n\" }
        }

 

ソースコード全体では以下のようになります。

#!/bin/bash
expect -c "
        # タイムアウト設定
        set timeout 10

        # SSH
        spawn ssh user@192.168.0.10

        # 修正箇所★★
        expect {
                default { exit 3}
                \"assword:\" { send \"my_password\n\" }
        }
        expect \":~\"
        interact
"

 
これで再度試したところ、意図通りタイムアウトし、終了コードも3になりました。

# time sh expect_test.sh
spawn ssh user@192.168.0.10

real    0m10.009s
user    0m0.004s
sys     0m0.002s
# echo $?
3

 
ちなみにログイン自体が成功することも確認しています。

# sh expect_test.sh
spawn ssh user@192.168.0.10
user@192.168.0.10's password:
Welcome to Ubuntu 16.04.4 LTS (GNU/Linux 4.4.0-116-generic x86_64)

Last login: Tue Jun 12 14:48:32 2018 from 10.254.14.120
user@remote_server:~$

まとめ

と言うことで、expectコマンドを使って自動化するときの注意点のメモでした。
このコマンドはなかなかクセがあり、使いこなすのが難しいですね。


スポンサーリンク




コメント一覧


コメントを投稿する


お名前


コメント内容





TOP back