expectコマンド 基本の使い方。

サーバーに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パスワードログインの自動化をする。

コメント

タイトルとURLをコピーしました