2012年9月9日日曜日

自動操作 expect tcl

出稼ぎ先の案件で、サーバ40台更新とかあります。

クラウドな昨今では、少ない方だとは思いますが、インフラ管理が、発注元なので、かなり勝手が違います。要するに、自動化/合理化がしにくいシチュエーションです。

具体的な作業は小生ではありませんが、slogin/sudo合わせて、100回近くパスワードを打ってるのは、端から見て大変過ぎます。見かねて先方に、authorized_key入れていいですか?と聞いたら断られて、代わりにexpectでナントカしてと言われまして。そーいや10年ぐらいまえにも聞いたことあるぞと。

仮にauthorized_keysを入れたとして、リモートの向こうのsudoはどうにもなりません。前の前の出稼ぎでは、root同士でauthorized_keyしてたらしい。やったのは小生じゃないです。ただこれネットワーク管理的にNo Goodであるのは大いに納得できます。

http://en.wikipedia.org/wiki/Expect
http://www.nist.gov/el/msid/expect.cfm
http://sourceforge.net/projects/expect/

元々はtcl/tkの拡張のひとつらしいのですが、tclを知ってる小生は作業時間がとれず、若いのに頼んでみたら、二日で覚えました。若いってのはいいです。

Expectの方法論は簡単で、「人間がする操作を、代わりにやる」というもので、「書き置きしたシェルスクリプトを流し込む」とは真逆です。もちろん、前者は結局は、「expectスクリプト」になるので、効果は似たようなものです。

spawn telnet $arg(0)
expect "login: "
send "$arg(1)\n"
expect "Password: "
send "$arg(2)\n"

ハイ、もう判りましたね的な簡単さ。ただし実際にはもうちょっとコツが要ります。

クラウド時代的にはちっとも流行りじゃないので、割と古い記述しか見つかりません。当時と現在とで違うのは、イタズラへの耐性。最近のslogin/sudoは、プロンプト待ちで、標準入力を一旦捨てるっぽいです。

spawn telnet $arg(0)
expect "login: "
sleep 1
send "$arg(1)\n"
expect "Password: "
sleep 1
send "$arg(2)\n"

頭悪そうに見えますが、諦めましょう。人間が操作する場合を思い出して欲しい。「おっとパスワード入れなきゃ」、と操作にはさまざまなタメがあるはずで、それすら再現してあげる必要があります。「人間のための機械」を操作させるためには、「人間型のロボットが都合がいい」的なアレです。

もうちょっとちゃんとやってる実装も見つけました。https://github.com/cvmiller/expect-lite/blob/b1f3a3596108b88bc8433953dade3a56325e83fa/sudo.tcl

なお、クラウド時代には、こんな中途半端な自動化は恐らく流行りません。
  • バージョンアップは、P2Pを応用して、数100台を数分で。http://torrentfreak.com/twitter-uses-bittorrent-for-server-deployment-100210/
  • 新しいVMを起動時に、S3から最新版を持ってきて勝手にデプロイ
    • 完全自動も出来なくはないが
    • Amazon EC2なら、インスタンスにrootログインが出来るので、外部からスクリプト流し込む。という切り札もなくはない。
そんな世の中ですから。

とはいえ、ちょっと探してみると、なかなか面白い応用があるっぽいです。

小生は、appengine python SDKのデプロイ時に、メイルアドレスとパスワードを入れるのに使ってます。