Lから始まるLinux

3章29話
ANSIエスケープシーケンス
3章30話 expectコマンド
もくじ
4章1話
スーパユーザ
expect コマンド
若木 みどり
お兄ちゃん! シェルスクリプトに 「対話的」なコマンドがあると 自動化がしにくいよ! 問い合わせが来るから そこで手を止めないと いけなくなっちゃうんだ!
若木 しげる
対話的なコマンドは 入力リダイレクトやパイプから 自動化できる場合があるよ 以下は yes を使った例だよ
yes | 対話的なコマンド
若木 しげる
でも一部のコマンドは入力リダイレクトやパイプからの入力を拒否するんだそのようなコマンドにpasswdssh などがあるよ
若木 しげる
expectそのような入力を拒否する対話的コマンドでも対話を自動化できるようにしてくれるんだ!
若木 しげる
今回は expect を使って対話的なコマンドの対話を自動化しよう!
使い方
若木 しげる
expect対話的なプログラムのやりとりを自動化してくれるツールだよ
expect [オプション]... [引数]...
若木 しげる
expect はスクリプト言語なんだシェルスクリプトのようにexpect コマンドを書いていきそれを実行することで対話を自動化してくれるんだ
若木 みどり
expect 独自のコマンドを覚える必要があるのね…
若木 しげる
expect のコマンドはたくさんあるけどいくつかを覚えれば十分自動化できるんだ最初は以下を覚えよう!
expect コマンド役割
spawn コマンドコマンドexpect の管理下で実行する
sleep 秒数秒数 間待機する、小数の指定も可能
expect 文字列expect 管理下のコマンドが指定された文字列を出力するまで待機する
send 文字列expect 管理下のコマンドに文字列を送る
waitexpect 管理下のコマンドが終了するまで待機する
closeexpect 管理下のコマンドを終了する
実践
若木 みどり
説明だけだと使いこなせる気がしないよ実例が見てみたいなぁ
若木 しげる
それでは expectpasswd の対話を自動化してみよう!
USERNAME=midori
sudo expect << EOF
spawn passwd "$USERNAME"
expect "New password:"
send "$USERNAME\r"
expect "Retype new password:"
send "$USERNAME\r"
wait
EOF
若木 しげる
最初の1行で変数を定義している以外はexpect の処理だよ!
若木 みどり
expect の前にsudo ってあるね?確か管理者権限でコマンドを実行だったはずだけど…
若木 しげる
他人のパスワード変更は管理者の仕事なのでsudo が必要なんだ詳しくは管理者を説明するときに話すね
若木 みどり
expect のヒアドキュメントの内容がexpect スクリプトになっているんだね!ここで自動化の指示をしているんだ!
若木 しげる
そういうことだよexpect スクリプトの内容を1行ずつ読み解いてみよう最初の行はどういう意味かな?
spawn passwd "$USERNAME"
若木 みどり
spawnexpect 管理下でコマンドを実行」だよねUSERNAME 変数にはmidori が入っているからこれは passwd midori実行してくれるんだ!
若木 しげる
passwd の引数にユーザ名を指定するとそのユーザのパスワードを変更するよつまり passwd midorimidori ユーザのパスワード変更なんだこれで passwd コマンドがexpect の管理下で実行されるよ
若木 しげる
さて…その次の行はどうだろう?
expect "New password:"
若木 みどり
expect「管理下のコマンドが指定された文字列を出力するまで待機」だったねpasswd「New Password:」という文字列を出力するまで待機するんだ!
若木 しげる
そういうことだね!待ち受けメッセージが表示されてからパスワード入力を受け付けるのでそれが表示されるまでは待機しているんだ
若木 しげる
さらにその次はどうかな?
send "$USERNAME\r"
若木 みどり
send「管理下のコマンドに文字列を送信」だったねUSERNAME 変数の値midori を送って…
若木 みどり
えっと…最後の \rなんだろうね?
若木 しげる
これは expect「改行」を表す記号だよ
若木 みどり
なるほど!それなら「New Password:」待ち受けメッセージが表示された後に文字列 midori「改行」送信しているんだ!
若木 しげる
そうそう!これで最初の「New Password:」入力を自動化しているんだ
若木 しげる
次の2行もこれまでと同じ挙動だね
expect "Retype new password:"
send "$USERNAME\r"
若木 みどり
うん!入力パスワード確認も同様に自動化しているんだね!
若木 しげる
次で expect スクリプトの記述は最後だね
wait
若木 みどり
「New password:」「Retype new password:」に対して自動でパスワードを入力した後passwd が終了するまで待機しているんだ!
若木 しげる
おつかれさま!これで expect を使ったpasswd の対話の自動化が終わりだよ
まとめ
若木 みどり
今回は expect を使って対話的コマンドの対話自動化を学んだよ!
若木 しげる
対話的なコマンドを入力リダイレクトやパイプで自動化できなければexpect の出番だよ!