expect:対話コマンドで自動実行

Linuxコマンド


対話式コマンドでコマンドを自動実行させたい場合に使用するコマンドです。

インストール

# yum install expect


使用方法

#!/usr/bin/expect

set timeout 5
spawn ssh www.hoge.co.jp
expect "Enter passphrase for key"
send "hogehoge38\n"
expect "Last login"
send "ls -l\n"
interact


set timeout

設定した秒数の間、標準入力から応答がないとexpectは、終了します。上記例だと、5秒 でタイムアウトする設定になります。
「-1」を設定すると、タイムアウトしない設定に なります。

spawn

自動で実行したいコマンドを指定します。上記の場合、「ssh www.hoge.co.jp」を実行します。

expect

指定された文字列(「”」に囲まれた文字)と標準入力のデータとを正規表現で比較し、一致するまで以降の命令を実行しません。例だと、「Enter passphrase for key」が、画面に表示されるのを待つことになります。

send

指定された文字列(「”」に囲まれた文字)を先に実行したコマンドのジョブに送信します。つまり、「hogehoge38\n」とパスフレーズを入力したことになります。文字列最後の「\n」は、改行(Enterを押下)を意味します。

interact

実行ジョブの標準入出力をキーボードと画面にします。これで、自動実行を終了し、端末からsshでログインしたのと同じ状態になります。

log_file

log_file ./expect_`date +%Y%m%d`.log
結果を指定したログへ出力できます。

実行結果は、次のようになります。sshでログインした後、「ls -l」を実行し、制御を端末に戻しています。

条件分岐

expectで条件分岐させるのは{}を使用することで可能です
下記スクリプトはSSH自動ログインして、rootまであがるスクリプトです。
{}の位置について、改行したりするとコマンドが実行されないので、下記文法の通りにすると良いです。

#!/bin/bash

export LANG=C

USER=user
PASS1=userpass
RPASS1=rootpass
HOST=$1

# expect コマンドを実行
expect -c "

# タイムアウト値の指定
set timeout 10

# spawnで新しいジョブ生成
spawn ssh ${USER}@$1

# login
expect \"Are you sure you want to continue connecting (yes/no)?\" {
  send \"yes\n\"
  expect \"$USER@$HOST's password:\"
  send \"${PASS1}\n\"
} \"$USER@$HOST's password:\" {
  send \"${PASS1}\n\"
}

# rootへ昇格
expect ${USER}
send \"su\n\"
expect Password:
send \"${RPASS1}\n\"

# logout
expect root
send \"exit\n\"
expect ${USER}
send \"exit\n\"

# spawnジョブを通常の通信にする
interact
"