*趣旨 [#c31deb5e] Linux系のコマンドを扱っていると対話型のコマンドが多いので expectをつかった自動化についてまとめる。 *目次 [#zf5e7d4c] #contents *expectとは [#d053b40a] expectはTclの拡張ライブラリで、対話型の入力が必要な時の自動実行ツールで有名です。Tclのプログラムがそのまま使えるらしいのです。 -拡張デバッグ・オプション -文字指向型のダイアログを記述するための便利なコマンド -面倒な文字指向型端末に対するこの上なく優秀な管理 **サーバー・クリニック: 期待以上の出来のExpect [#xea08193] http://www.ibm.com/developerworks/jp/linux/library/l-sc1/ **Tclの文法などの概要(Wiki) [#x106a64a] http://ja.wikipedia.org/wiki/Tcl/Tk *リンク [#b7eb913e] **本家(英語) [#wf646e1d] http://expect.sourceforge.net/ **Tcl [#p1426b50] http://www.tcl.tk/ ***Tcl基礎文法最速マスター [#gab3fffd] http://pyomeha.blog42.fc2.com/blog-entry-6.html ***マニュアルページ [#h743322c] http://www.tcl.tk/man/tcl8.5/ **DejaGnu [#e35b7333] DejaGnuは他のPCをテストするフレームワークです。Expectで書かれており、すなわちTclで書かれているわけです。 http://www.gnu.org/software/dejagnu/ **ExpectPy [#ha1cfd6e] TclのかわりにPythonで書かれたライブラリかも http://expectpy.sourceforge.net/ **Rubyのexpect.rbの使い方 [#c3365d9b] http://rakuto.blogspot.jp/2006/09/rubyexpectrb.html http://www.42klines.com/2010/08/14/what-to-expect-from-the-ruby-expect-library.html ***Ruby expect 条件文(if文)の書き方 [#f4a66012] http://oshiete.goo.ne.jp/qa/4864602.html ***telnet自動化のサンプル [#ae38fdd2] http://www.webhtm.net/blogger/2008/10/rubyexpect-expectrb.html ***リファレンスマニュアル [#y3b90d9e] http://www.ruby-lang.org/ja/old-man/html/expect.html **PHPをつかった例 [#t86ca016] http://php.net/manual/ja/expect.examples-usage.php ***Javaの場合:ExpectJ [#cf621a4b] http://expectj.sourceforge.net/ *心構え [#x43689fd] 運用を定型化したほうがよい。たとえば実行した結果をwiki等に反映させるとか。 定型化するときに、対話が必要ではない箇所はシェル化しておいたほうがよい。 理由はexpectのスクリプトを書くよりも、シェルを書いたほうが楽 パスは絶対パスでかいておいたほうがよい。理由は、expect内では、シェルの変数とかが使えなかったりするから。 exceptをつかうファイルは普段は暗号をかけ、アクセスできる権限を絞っておくことにしたほうがよい **ファイルの暗号化 [#he0bbb89] [Linux] ファイルを暗号化する方法あれこれ http://ameblo.jp/itboy/entry-10484615897.html *脆弱性チェック [#j11768b3] テキストファイルに暗号化をかけずにパスワードで保管しているのはよくないので自主的に脆弱性について検査しておくこと **Crack/Cracklib [#te2630f7] http://dropsafe.crypticide.com/article/1019 *逆引き [#la892440] **使用する言語の宣言をする [#xf6469d4] #!/usr/local/bin/expect -f (パスは環境によって変わります。) **10秒間応答がなければ終了させる [#tddd23ef] set timeout 10 **expectコマンド内でtelnetを実行 [#f796bbe1] spawn telnet 10.1.1.1 #expectコマンド内でtelnetを実行 **Password: 文字列が帰ってきたら [#uf1ba3c9] expect "Password: " **ログインパスワードaaaを入力 [#n12ae0de] send -- "aaa\n" **expectの終了 [#k36271f8] expect eof **引数の確認 [#c149c8b5] http://blogs.yahoo.co.jp/eguchium/50663261.html **複数の質問を想定 [#se444456] sshは1度目と2度目以降では質問がことなるので、その場合の記述例 expect \"Are you sure you want to continue connecting (yes/no)?\" { send \"yes\n\" expect \"work@srv01's password:\" send \"password\n\" } \"work@srv01's password:\" { send \"password\n\" } **ユーザの入力を促す [#pbca74f7] interact *サンプルコード [#e33e1e34] **パスワードを更新するための簡単なExpectプログラム [#o7025017] # Invoke as "change_password <user> <newpassword>". package require expect # Define a [proc] that can be re-used in many # applications. proc update_one_password {user newpassword} { spawn passwd $user expect "password: " exp_send $newpassword\n # passwd insists on verifying the change, # so repeat the password. expect "password: " exp_send $newpassword\n } eval update_one_password $argv ***Expectの自動化にGUIの外見をもたせる [#ufc45e54] package require Tk frame .account frame .password label .account.label -text Account entry .account.entry -textvariable account label .password.label -text Password # Show only '*', not the real characters of # the entered password. entry .password.entry -textvariable password -show * button .button -text "Update account" -command { update_one_password $account $password } pack .account .password .button -side top pack .account.label .account.entry -side left pack .password.label .password.entry -side left **interactをつかったサンプル [#f0fa5597] set CTRLZ \e032 interact { -reset $CTRLZ {exec kill -STOP 0} \e001 {puts "you typed a control-A\en"; send "\e001" } $ {puts "The date is [exec date]."} \e003 exit foo {puts "bar"} ~~ } **putsをつかったサンプル [#q629a41d] puts $time この辺はTclのコマンドをしらべたほうがいい ***Tclコマンド [#ofb82727] http://www.tcl.tk/man/tcl8.5/TclCmd/contents.htm **正規表現をつかったサンプル [#z556065c] regexp {([0-9][0-9]:[0-9][0-9]:[0-9][0-9])} $expect_out(buffer) _ time **if文をつかったサンプル [#z4f8a5be] if {[llength $argv] != 1} { puts stderr "Usage: daytime host" exit 1 } *未調査なコマンド [#u4891759] **dislocate [#ha0f0456] プロセスをやめたり、名前付きのプロセスにリモートで再接続することができるかも **cryptdir [#i77a7155] ディレクトリ内のファイルを暗号化するのにつかえるのかも decryptdir **kibitz [#l0c4cad2] 2人で1つのプロセスを触る時につかうのかも **mkpasswd [#u1686a36] パスワード自動生成 **passmass [#d43aecde] 複数台のDBのパスワード変更をおこなうことができるかも **tknewsbiff [#d7c5e7a6] おしらせがあったらポップアップウィンドウを開くのかも **unbuffer [#d9539de8] 出力をみたくない場合につかうのか? **xkibitz [#t98138cb] 1つのプロセスを複数のターミナルで扱うときにつかうのかも *留意点 [#t76bfaaa] 後々知ったことではあるが SSHではRuby/PythonなどのSSHライブラリを使うべきで、パスワードではなく証明書ログインをするべき。 だが、やりすぎると、自分の家の中のドアに全部鍵をつけるがごとくになりかねないので、そこはバランスをとろう