サーバーにsshログインする際には、パスワード入力しないといけない。
sudoコマンドを実行する際にもパスワードを入力しないといけない。
そういった場合に便利なexpectコマンドというものがあります。
このコマンド自体は、対話処理を自動化するためのコマンドです。
パスワード入力以外にも何かと用途はありそうです。
この記事では、expectコマンドの基本的な使い方について紹介していきます。
expect コマンドのインストールについてはこちらの記事を参考に。
expect コマンド インストール
expectコマンドとは
expect - programmed dialogue with interactive programs
対話シェルを自動化するためのコマンドです。
expectは期待するという意味なので、
何々と来たら、こういうコマンドを実行するといった感じで、
Tcl(Tool Command Language) [ティクル] という言語を使って表現する事になります。
言語自体はシンプルです。
もし、凝ったことを実現したければ、詳しく調べてみると良いでしょう。
Tclの文法について、
もう少し詳しく知りたいという方は、こちらの記事を参考にしてください。
必須の命令文
Tclで記述することになりますが、
expect用の命令(コマンド)がいくつか定義されています。
spawn
例
# sshプロセスを起動
spawn ssh taro@127.0.0.1
指定のコマンドを実行しプロセスを起動する。
Expectコマンドは、この起動したプロセスのstdin, stdout, stderrと接続した状態になります。
この起動したプロセスに対して、
後述するexpectや、sendを使って操作していく事になります。
expect
spawnで起動中のプロセスが、特定のパターンを出力するまで待機する。
例
# password と出力されるまで待機する。
expect "password"
待機時間はデフォルトで10秒です。
あらかじめ set timeout 5
としておくことで、待機時間(秒)を設定できます。
expectに指定するパターンは、単一だけでなく複数指定することも可能です。
マッチしたパターンに応じで分岐を書く事ができます。
expect {
busy {puts busy\r ; exp_continue}
failed abort
"invalid password" abort
timeout abort
connected
}
↑のパターンは、
connected という出力パターンがくるまで待機していて、
busy が来た場合は、画面にbusyと出力して、exp_continue で再待機しています。
failed や、その他のパターン出力時は、abortで終了しています。
指定するパターンは、デフォルトでglob形式での指定になります。
正規表現か完全一致で指定することもできます。
send
spawnで起動したプロセスに対して、入力メッセージを送信します。
末尾に\r
とリターンコードも指定する必要があります。
例
# 起動プロセスに対して、"date"と入力してEnter、というメッセージを送る。
send "date\r"
expectで期待する出力パターンが来たら、
このsendで入力したい内容を送るという感じで使用したりします。
interact
spawnで実行中のプロセスをユーザーに渡します。
キーボード入力は、そのプロセスに受け流しされるようになります。
なにもしないと、Expectコマンドはそのまま起動プロセスも一緒に終了させてしまうので、
sshをspawnさせてた場合など、そのまま対話シェルを続ける場合は、このinteractでユーザーに制御を渡すようにします。
簡単なサンプル
サーバーにsshするとして、
パスワード入力を求められたら、自動で入力してくれるような処理は下記のようになります。
sample.tcl
# sshプロセスを起動
spawn ssh taro@127.0.0.1
# password入力を求めてくるまで待機
expect "password"
# パスワードを入力(改行コードも忘れずに)
send "hogehoge\r"
# プロンプト($)が表示されるまで待機。
# (二重エスケープしている)
expect "\\\$"
# 制御をユーザーに渡す
interact
↑のファイルを、expectコマンドで実行。
# 実行
expect sample.tcl
sshした先で何かしたいという場合は、
spawnでsshプロセスを起動、
そのプロセスに対して、expectで待機して、sendでコマンドを送信するという形になります。
最後に、ユーザーに制御を渡したい場合は、interactしておきます。
(interactがないと、そのまま終了してしまいます)
まとめ
- spawn プロセスを起動する
- expect プロセスからのメッセージを期待する。
- send プロセスにメッセージを送る
- interact プロセスの制御をユーザーに渡す。
あと、注意点としてsendしたあとは、必ずexpectで何かしら待機したほうが良いです。
立て続けにsendすると、うまく実行されない場合があります。
サンプルコードのように、プロンプトの$
で待機しておくのが良いでしょう。
SSH接続時のパスワード入力自動化についてはこちらの記事を参照ください。
expectコマンドで、sshパスワードログインの自動化をする。