Linux系のコマンドを扱っていると対話型のコマンドが多いので expectをつかった自動化についてまとめる。
expectはTclの拡張ライブラリで、対話型の入力が必要な時の自動実行ツールで有名です。Tclのプログラムがそのまま使えるらしいのです。
http://www.ibm.com/developerworks/jp/linux/library/l-sc1/
http://ja.wikipedia.org/wiki/Tcl/Tk
http://expect.sourceforge.net/
DejaGnu?は他のPCをテストするフレームワークです。Expectで書かれており、すなわちTclで書かれているわけです。
http://www.gnu.org/software/dejagnu/
TclのかわりにPythonで書かれたライブラリかも http://expectpy.sourceforge.net/
http://rakuto.blogspot.jp/2006/09/rubyexpectrb.html
http://www.42klines.com/2010/08/14/what-to-expect-from-the-ruby-expect-library.html
http://oshiete.goo.ne.jp/qa/4864602.html
http://www.webhtm.net/blogger/2008/10/rubyexpect-expectrb.html
http://www.ruby-lang.org/ja/old-man/html/expect.html
http://php.net/manual/ja/expect.examples-usage.php
http://expectj.sourceforge.net/
運用を定型化したほうがよい。たとえば実行した結果をwiki等に反映させるとか。
定型化するときに、対話が必要ではない箇所はシェル化しておいたほうがよい。
理由はexpectのスクリプトを書くよりも、シェルを書いたほうが楽
パスは絶対パスでかいておいたほうがよい。理由は、expect内では、シェルの変数とかが使えなかったりするから。
exceptをつかうファイルは普段は暗号をかけ、アクセスできる権限を絞っておくことにしたほうがよい
[Linux] ファイルを暗号化する方法あれこれ
http://ameblo.jp/itboy/entry-10484615897.html
テキストファイルに暗号化をかけずにパスワードで保管しているのはよくないので自主的に脆弱性について検査しておくこと
http://dropsafe.crypticide.com/article/1019
#!/usr/local/bin/expect -f
(パスは環境によって変わります。)
set timeout 10
spawn telnet 10.1.1.1 #expectコマンド内でtelnetを実行
expect "Password: "
send -- "aaa\n"
expect eof
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\" }
interact
# 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
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
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 $time
この辺はTclのコマンドをしらべたほうがいい
http://www.tcl.tk/man/tcl8.5/TclCmd/contents.htm
regexp {([0-9][0-9]:[0-9][0-9]:[0-9][0-9])} $expect_out(buffer) _ time
if {[llength $argv] != 1} { puts stderr "Usage: daytime host" exit 1 }
プロセスをやめたり、名前付きのプロセスにリモートで再接続することができるかも
ディレクトリ内のファイルを暗号化するのにつかえるのかも
decryptdir
2人で1つのプロセスを触る時につかうのかも
パスワード自動生成
複数台のDBのパスワード変更をおこなうことができるかも
おしらせがあったらポップアップウィンドウを開くのかも
出力をみたくない場合につかうのか?
1つのプロセスを複数のターミナルで扱うときにつかうのかも
後々知ったことではあるが SSHではRuby/PythonなどのSSHライブラリを使うべきで、パスワードではなく証明書ログインをするべき。
だが、やりすぎると、自分の家の中のドアに全部鍵をつけるがごとくになりかねないので、そこはバランスをとろう