サーバー・クリニック: 期待以上の出来のExpect

知名度は低いが強力な機能を備えた人気のツール

Cameron Lairdが、人気のツールExpectについて概要を紹介する毎月のコラムを新たに開始します。この言語は、ほとんどのプログラマーやアドミニストレーターの予想をはるかに上回る機能を備えています。Expectは、サーバーを十全な状態に維持するための広範な作業に適していますので、これだけでほとんどの処理が可能な汎用的なプログラミング言語として利用できます。

Cameron Laird (Cameron@Lairds.com), Vice President, Phaseit, Inc.

Photo of Cameron LairdCameronは、Phaseit, Inc. の常勤のコンサルタントです。オープン・ソースなどの技術的なトピックについて、数々の執筆や発言を行っています。Cameronのメール・アドレスはclaird@phaseit.net です。



2002年 4月 01日

みなさんは「システム・プログラマー」です。サーバーを十全な状態に維持するためのコードや、同僚のアプリケーション開発プログラマーが必要としている低位の機能を提供するためのコードを書いています。みなさんは、必要な情報をどこから仕入れていますか。プログラミング解説書が扱っているのは、たいていクライアントや「アプリケーション」の問題が中心ですし、管理に関する文献は、「構成」が中心で、プログラミングには言及しないのが常です。

そこで私は、この新しい「サーバー・クリニック」のコラムが、みなさんの役に立つ情報源の1つになればと願っています。毎月、プログラミングの問題や、サーバーの「世話や管理」に共通する一連の問題を1つずつ解決していきたいと思っています。

今回の第1回目では、Expectを取り上げます。ほとんどの読者が知っておいて損のない言語です。多分すでにExpectのことをご存じでしょう。しかし、Expectでどんな作業が出来るかを、完全に把握されている方も少ないというのも事実です。Expectは、Linuxのシステム・プログラミングに求められる一種の汎用性を実現しています。これは、他の言語では (CやJavaやbashですら) 得られない能力です。このコラムでは、今後、さまざまな言語での解法を紹介するつもりですが、Expectが最も多く登場する言語になることと思います。

Tclがベース

Expectが「汎用的」なのは、なぜなのでしょうか。まず、Expectがプログラミング言語Tcl/Tkの正真正銘のスーパーセットであることを頭に入れておいてください。Tclは、様々なプログラムに使用される高級言語です。Tclは、よく、PerlやPython、Rubyなどといっしょに「スクリプト」言語として分類されます。2002年の現在では、歴史的な経緯にはとらわれず、これらの言語を、高度に生産的なオープン・ソース言語として考えるのが最も賢明です。Tclは、とくにコンピューター支援設計 (CAD) の分野やCiscoやNortelなどのネットワーキング機器ベンダーで好んで使われてきました。他の「スクリプト」言語と同様、Tclに組み込まれている機能は、テキスト処理やデータベース管理、ネットワーキング、計算などのほとんどの一般的な問題に適用できます。

TclがExpectのベースです。Tclのプログラムは、自動的にExpectのプログラムでもあります。このことを強調するのには、いくつかの理由があります。

  • 多くの人は、Expectを単に「ツール」として考えており、本格的なプログラミング言語であるという認識がない。
  • Expectの汎用的な能力を認識しているプログラマーでも、多くは、1994年時点の認識に留まっている。

Expectの作者は、米国National Institute of Standards and TechnologyのDon Libes氏です。1994年、氏は、Expectについての素晴らしい書籍を出版しました。この本は、まだ初版のままですが、競合する本はありません。非常によく書かれているため、別の書籍を出す出版社は現れていません。非常に珍しいことですが、Exploring Expect (稿末の参考文献参照) は、改訂を必要としなかったのです。その明解さと正確さは、年を追って評価されてきました。

しかしこのことは、ExpectのベースであるTclが、この8年間大きく進歩したという点で問題でもあります。Expectが最初に作成された時点で、Tclは、汎用的なプログラミング言語になることを目指していませんでした。その後Tclは、

  • 完全8ビット・データ、さらにはUnicodeまでも手際よく処理できるようになり、
  • 便利なTCP/IP抽象 (abstraction) を追加し、
  • データや時刻の計算や書式指定の機能を獲得し、
  • 文字列処理の方法を改良し、合理的なものにしてきました。

ですから、ある問題がPerlやJavaやCで解決できる場合、多分Tclでも、したがってExpectでもそれが可能だ、ということを頭に入れておいてください。

逆に、Tclが他の言語より格段に優れている点として、グラフィカル・ユーザ・インターフェース (GUI) の構築があります。ActiveState Tools CorporationからダウンロードできるLinux向けの標準的なActiveTclバイナリー・ディストリビューションの場合、約10 MバイトのサイズにExpectだけでなく本格的な統合型GUIツールキットまで含まれています。後で出てくる例では、このTkと呼ばれるツールキットがGUIソリューションをいかに簡潔に表現できるかを紹介したいと思います。


難しい問題をユニークな方法で解決

ExpectのベースであるTcl/Tkは、極めて広範なプログラミングに応用することができます。Tcl/Tkのできることは、すべてExpectでもできるということを忘れないでください。それとともに、Expectは、大雑把な分け方をすると、以下の3つの機能を付加しています。

  • 拡張デバッグ・オプション
  • 文字指向型のダイアログを記述するための便利なコマンド
  • 面倒な文字指向型端末に対するこの上なく優秀な管理

このうち1つ目の機能は、従来型のものです。Expectには、その処理のいろいろな側面を記録、報告するための「スイッチ」がたくさん用意されています。

Expectの目的は、文字指向型の対話を自動化することにあります。みなさんも、こうしたことをたくさん経験しているはずです。コマンド・ラインでパイプラインを記述したり、入出力ストリームのリダイレクトを行うときには、そういうものを利用しない場合には、タイプ入力しなければならないような作業を、コンピューターにやらせているはずです。

Expectは、この制御を2通りのやり方で深めています。1つは、複雑なダイアログを表現するための言語を用意しているという点です。単に、アプリケーションへの入力となる固定的な「スクリプト」を使用するだけでなく、Expectは、対話の中で使用されるすべてのキーストロークをプログラムできるようにしています。

しかし、もっと重要なことは、Libesが述べているように、「Expectは、結局のところ、出来の悪いインターフェースに対処するために作られたツールである」ということです。とくに、Expectは、I/Oリダイレクションになじまないアプリケーションを管理するための、ありとあらゆる情報を備えています。典型的な例に、コマンド・ラインからのpasswd プログラムがあります。サーバーを管理している人なら、遅かれ早かれ、パスワードの更新を自動化する必要がでてきます。一番最初に考えるのは、ルート・ユーザーとして以下のようなことを実行しようということではないでしょうか。

失敗に終わるpasswdの自動化
passwd $user << HERE
	$newpassword
	$newpassword
	HERE

やってみればすぐに分かることですが、これはうまくいきません。シェルの < や << のリダイレクションは、passwd のようなプログラムではうまく働きません。

でもExpectは、それをやってのけます。Expectは、どんな文字指向型のアプリケーションとでも対話する術を知っています。たとえpasswd などのように端末の設定を操作するものであってもです。

これによって、Expectの汎用性は完璧なものになっています。他の言語やライブラリーも、大体は、端末の特性についての知識を提供するでしょう。たとえば、PerlのExpect.pm モジュールは、そういう意味で大きな役割を果たしています。しかし、製品化されて10年以上経過した今でも、Expectに充分対抗できそうな競合製品は現れていません。

これが、Expectの習得をお薦めする理由です。みなさんも、「出来の悪いインターフェース」を備えたプログラムを扱うことになるでしょう。そのようなプログラムは、ごろごろ存在します。Expectを使えば、そうしたプログラムに、目的とする処理をやらせようとするときの開発時間を、何時間も、場合によっては何日も節約できるのです。同時に、bashやPerlで処理されることの多い仕事についても、すべてExpectを使うことができます。


その他Expectについて知っておくべきこと

その他、Expectについて知っておくべきことがいくつかあります。今回の締めくくりとして、Expectの限界についての説明、一般的な問題を解決しているExpectの実際のコードの例、およびExpectプログラミングの理解を深めるための参考文献を紹介しておきます。

Expectは、ほとんどの人が認識している以上のことを行うことができます。そのことが、今回のコラムの主要なテーマです。しかし一方で、予想以下のことしかできない面もあります。システム・プログラマーは、FTP処理とか、電子メールの送信や取り扱いとか、GUIのテストなどを自動化する必要がよくあります。このうち最初の2つについては、Expectは役に立ちません。もっと正確に言うならば、FTPや電子メールの自動化にExpectを利用することもできますが、昔はそれも一般的でしたが、現在、これらの分野にExpectでなければならないという点はありません。他の言語や方法でもかまいませんし、そのほうがExpect指向のコーディングよりも優れていたりします。これについては、この「サーバー・クリニック」のコラムで、いつか、簡単なネットワーキングの自動化の例を紹介したいと考えています。

Expectが利用される分野の1つとして、テストの分野がよく知られています。Expectは、gccなど数々の有名な製品の品質管理に使用されているDejaGnuシステムの基礎を担っています。ただし、ExpectがGUIの構築に利用できたり、Expectがいろいろなテスト・フレームワークに欠かせないとはいっても、通常ExpectがGUIシステムのテスト・フレームワークで何らかの役割を果たしているという訳ではありません。

上で触れたpasswd の問題に少し話を戻してみたいと思います。Expectは、この問題をどう捉えているのでしょうか。

Expectのソースが理解しやすくなるように、とりあえずは、セキュリティーの問題は無視することにします。下のプログラムは、「ルート」ユーザーとして実行する必要があります。Expectには、もっと安全に処理を行うための便利な機能も備わっていますが、Expectの基礎をマスターしてからのほうが、そうした機能は理解しやすいでしょう。

passwd に単純なI/Oリダイレクションが使えないことは、先に触れたとおりです。どんなExpectプログラムにすれば、有効な結果が得られるでしょうか。

パスワードを更新するための簡単なExpectプログラム
# 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以外の言語ではほとんど実現できそうもありません。あと何行か足してやるだけで、何百人ものユーザーの更新を一括してバッチ処理することもできます。こうした要求は、よくあることです。私は、パスワード・ファイルが激しく損傷したサーバーを復旧してほしいということで呼び出されることがよくあります。その場合、まずは以下のようなコードで復旧を図ることになります。

単純な反復
  ...
   set default_password lizard5
   set list [exec cat list_of_accounts]
   foreach account $list {
       update_one_password $account $default_password
       puts "Password for '$account' has been reset."
   }

GUIも

Expectの自動化にGUIの外見をもたせるのも、たった数行を追加するだけのことです。プログラマーでない人に、パスワードを簡単に更新できるようなアプリケーションを提示したいとします。ここでもセキュリティーの問題は度外視するとすると、以下のように簡単に実現できます。

単純な反復
 ...
   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

これは、小さくても実際に動くアプリケーションで、下のような外観をもちます。

Expectによる簡単なパスワード・マネージャーのスクリーン・ショット
図1

まとめ

Expectは、システム・プログラマーが必要とすることの多いユニークな機能を備えています。と同時に、Expectは、ネットワーキングやGUIの構築を得意とする素晴らしい汎用プログラミング言語でもあります。日常の作業に使う言語を1個だけ選ばなければならないとすれば、Expectがほぼ理想的です。

みなさんがExpectをどんな用途に使っているのか、あるいは、どんなことに使いたいのか、お知らせください。これから数ヶ月、この「サーバー・クリニック」のコラムでは、ハイエンドなバージョン管理、ネットワーク・プロキシーなどの自動化のテーマに立ち返ってみたいと思います。それまで、みなさんとみなさんのサーバーが元気でありますように。

参考文献

  • TclプログラマーのWiki page on Expect は、多くの人が協同で維持・管理している情報ソース・サイトで、Expectのホームページやいろいろなアーカイブ、チュートリアル、関係情報などへのリンクが適宜更新されています。
  • What is Tcl では、Expectが定義する言語が解説されています。
  • Wiki page on Tk は、Expectに組み込まれているGUIツールキットを紹介しています。
  • ActiveTcl は、Tcl/Tkの無料のブランド・ディストリビューションで、コアのTclを拡張するさまざまな製品といっしょにExpectが掲載されています。
  • Exploring Expectは、Expectを言語的に定義するだけでなく、TclとTkについての簡単な入門解説も紹介しています。
  • DejaGnu は、非常に大きな効果をもたらすので、広く利用されているテスト・フレームワークです。
  • Android は、GUIアプリケーション向けの面白いテスト・フレームワークの名前です。AndroidとExpectには、かすかな繋がりがあります。
  • developerWorks のLinuxゾーンには、他にもLinux関係の記事が多数掲載されています。

コメント

developerWorks: サイン・イン

必須フィールドは(*)で示されます。


IBM ID が必要ですか?
IBM IDをお忘れですか?


パスワードをお忘れですか?
パスワードの変更

「送信する」をクリックすることにより、お客様は developerWorks のご使用条件に同意したことになります。 ご使用条件を読む

 


お客様が developerWorks に初めてサインインすると、お客様のプロフィールが作成されます。会社名を非表示とする選択を行わない限り、プロフィール内の情報(名前、国/地域や会社名)は公開され、投稿するコンテンツと一緒に表示されますが、いつでもこれらの情報を更新できます。

送信されたすべての情報は安全です。

ディスプレイ・ネームを選択してください



developerWorks に初めてサインインするとプロフィールが作成されますので、その際にディスプレイ・ネームを選択する必要があります。ディスプレイ・ネームは、お客様が developerWorks に投稿するコンテンツと一緒に表示されます。

ディスプレイ・ネームは、3文字から31文字の範囲で指定し、かつ developerWorks コミュニティーでユニークである必要があります。また、プライバシー上の理由でお客様の電子メール・アドレスは使用しないでください。

必須フィールドは(*)で示されます。

3文字から31文字の範囲で指定し

「送信する」をクリックすることにより、お客様は developerWorks のご使用条件に同意したことになります。 ご使用条件を読む

 


送信されたすべての情報は安全です。


static.content.url=http://www.ibm.com/developerworks/js/artrating/
SITE_ID=60
Zone=Linux, Open source
ArticleID=230674
ArticleTitle=サーバー・クリニック: 期待以上の出来のExpect
publish-date=04012002