やりたいこと
会社で自動化したい処理がいくつかあり、その中に対話形式のプログラムがあるため expect を利用することに。
初めて expect を使うため、下記の記事を参考にして簡単なプログラムを作ってみましたのでメモ。
「とりあえず動かしてみたい!」という方には参考になるかもしれません。
参考記事
Linuxの対話がめんどくさい?そんな時こそ自動化だ!-expect編-
インストール
以下の方法で expect コマンドをインストールします。
ちなみに OS は CentOS 7.6 で実行しています。
$ sudo yum install expect
簡単な対話プログラムを自作
expect のテストとして使えそうな簡単な対話プログラムがなかったので自作しました(シェルのお勉強を兼ねて)。
# !/bin/bash
GetInfo() {
item=$1
read -p "${item}: " val
echo ${val} # 受け取った値を標準出力することで値を渡す
}
SelfIntroduction() {
name=`GetInfo name` # 関数の結果を変数に代入する場合、関数名をバッククオートで囲む
age=`GetInfo age`
echo "Hello! I'm ${name}, ${age} years old."
}
SelfIntroduction
実行すると対話形式で name
と age
を聞かれ、入力が終わると Hello! I'm [名前], [年齢] years old.
と出力されるだけの簡単なプログラムです。
実行した結果
$ sh self-introduction.sh
name: Katsuo
age: 11
Hello! I'm Katsuo, 11 years old.
expect を使ってみる
上記のプログラムを対話せずに実行するため expect を使ってみます。
名前と年齢の値は引数として渡します。
expect には書き方が2パターンあるようで、1つはコマンドとして書く方法、もう1つはプログラム言語っぽく書く方法です。
両方のパターンを試してみましたが、可読性などを考えると後者がおすすめです(ネットを調べるとなぜか前者で書かれていることが多い)。
今回は後者のプログラム言語っぽく書く方法でやってみます。
プログラム言語っぽく書いてみる
以下が完成版です。
これでプログラムと対話することなく、名前と年齢を引数として渡すことで実行することができます。
# !/usr/bin/expect
set name [lindex $argv 0]
set age [lindex $argv 1]
spawn ./self-introduction.sh
expect {
"name" {
send "${name}\n"
exp_continue
}
"age" {
send "${age}\n"
exp_continue
}
"\\\$" {
exit 0
}
}
exit 0
実行してみる
以下の1行目を実行するだけで、止まることなく最後まで処理が実行されます。
$ expect self-introduction.exp Katsuo 11
name: Katsuo
age: 11
Hello! I'm Katsuo, 11 years old.
簡単に解説
# !/usr/bin/expect
いわゆるシバンです。
「これから expect でプログラム書きますよ!」というお知らせです。
set name [lindex $argv 0]
set age [lindex $argv 1]
引数として受け取った値を変数に入れてます。
spawn ./self-introduction.sh
spawn
で指定した対話プログラムが自動化の対象となります。
今回は同じディレクトリ内にある self-introduction.sh
を対象としています。
expect {
...処理...
}
expect { }
の中に自動化するための具体的な処理を書いていきます。
"name" {
send "${name}\n"
exp_continue
}
"age" {
send "${age}\n"
exp_continue
}
"\\\$" {
exit 0
}
name
でパターンマッチしたら、変数 ${name}
を入力してリターンします。
同様に、age
でパターンマッチしたら、変数 ${age}
を入力してリターンします。
exp_continue
を入力しておくことで expect { }
ブロックから抜け出さずに処理を続けることができます。
\\\$
の部分は、プロンプトの入力待ち状態になったら expect { }
ブロックから抜け出すための処理です。
プロンプトは環境によって異なるため、#
や %
などに編集が必要な場合があります。
(コマンドプロンプトを起動して、入力待ちのときに表示される記号のことです。)
また、詳しい理由は分かりませんが \
3つ必要です。
内部でどのような処理が行われているか不明ですが、エスケープが2回必要みたいです。
以上!