システム管理者のために

たとえ扱うコンピュータは少なくてもシステム管理者の仕事は大変なもの。連載のまとめとして、ハイパーカードオフィスを円滑に運用するための方法を考える。

自動的なアップグレード

スタックを使った業務支援システムは、自分たちで試行を繰り返しながらいろいろと改良を加えていくことができる。HyperTalkはプログラムをコンパイルしないインタープリタ言語なので、アイデアをその場で試してみることが可能だ。これは出来合いの業務用アプリケーションでは得られない、ハイパーカードならではのメリットである。

しかし、こうして新たな機能を追加したスタックを、毎回全員に配布していくのは骨が折れる。1台や2台のコンピュータならともかく、オフィス全体のマッキントッシュに新しいスタックをコピーして回るのは、楽な作業ではない。システムを改良すればそれだけ自分の仕事が増えるというのでは、管理者の開発意欲も殺がれてしまう。ある程度の規模のシステムを運用するようになったら、やはり自動的なメンテナンスの仕組みを用意したいものだ。

スタックのコピー

新しいシステムをユーザーのコンピュータに自動的に反映させるのは、これまで何度か検討してきた起動時の定型作業によって実現できそうである。ハイパーカードが立ち上がるときに行う作業はスタックのon startUpハンドラで定義できるから、ここにシステム更新用の命令を組み込んでおけばよい。この命令は、サーバーに置いたシステムの更新情報をチェックし、新しいものが用意されていればユーザーのスタックをそれと交換するような仕組みになるだろう。

この方法を実現するには、考えなければならない点が2つある。まず第1に、HyperTalkにはファイルをコピーする命令が用意されていないこと。テキストファイルならいったん内容をメモリに読み込んでから別のファイルに書き出すという方法でコピーできなくもないが(作成日付やクリエイターなどの情報は保持できない)、スタックのようなバイナリのファイルはそういう訳に行かない。スタックの場合は、save命令を使って

save StackA as StackB

のようにバックアップコピーを作成すれば複製は可能なのだが、StackBがすでに存在するとこれはエラーになってしまう。つまり、この命令では同じ名前のスタックをアップグレードすることは出来ないのである(*注1)。

こればかりはどうしようもないので、XCMDのお世話になることにしよう。ここではF.Rnaldi氏が作成したFileCopyを利用する。この外部命令はあらゆるタイプのファイルをコピーできるだけでなく、オプションで既存のファイルの上書きを指定することも可能だ。スタックの更新に限らず、幅広い用途に活用できる強力なツールである。

自分自身を書き換える?

もう一つ注意すべき点は、このアップグレード命令は、自分自身を更新するためには使えないということだ。スクリプトを実行している途中にスタックが書き換えられてしまうと、そのスクリプトが終了した時点でハイパーカードは混乱してしまい、正しい動作が出来なくなる(*注2)。したがって、スタックのアップグレードは別のスタックから指示を出すようにしなければならない。

これをうまく処理するためには、(ローンチャのような)メインのプラットフォームとして利用するスタックの他に、起動処理専用のスタックを用意する必要がある。このスタックはシステムフォルダの起動項目に登録し、電源を投入すればかならず立ち上がるようにしておく。そして、システムの更新などの起動作業を終えたら、制御をメインのスタックに渡してやる(つまりgo stack <mainstack>とする)わけだ。

この起動用スタックそのものの更新は手作業でやるしかないので、これはできるだけシンプルなものにしておくのがよい。本体に組み込む機能は絞り込み、細かい作業の指示は外部のファイルに持たせてdo命令で実行する(*注3)ようにしておけば、機能の追加変更は自由である。

システム更新のためのスクリプト

以上の点を考慮して作成したスクリプトがリスト1のものである。このハンドラは起動スタックのon startUpから呼び出され、アップグレード用のスクリプトファイルをチェックする。スクリプトファイルの1行目に書き込んだ更新指示のサインを前回のサインと比較し、新しい指示があった場合のみ更新スクリプトを実行するというものだ。

ここでいうスクリプトファイルとは、リスト2のような具体的なアップグレードの命令を書き込んだテキストファイルである。1行目は前述した更新指示サイン。前回のサインはスタックのフィールドに保存されているので、upGradeハンドラはこの行をフィールドと比較し、新しい指示が出ていれば続く内容を実行する(--を使ってコメントにしておかないと実行エラーになるので注意)。残りは見ての通りだが、6行目がRnaldi氏のXCMDを使う部分だ。引数は順にコピー元のファイル、コピー先のフォルダ、既存ファイルを書き換えるという指示になっている。

この仕組みは、外部ファイルに命令を列挙するようになっているから、単なるコピー以外の特殊な更新を行う場合も、そのファイルに指示を追加したり書き換えたりするだけでよい。その気になれば、このファイルに記述した命令だけで、(新しいものをコピーするのではなく)スタックの内容をすっかり書き換えることも可能である。このように起動スタックのスクリプトに手を加えずに柔軟な処理をさせるメリットは、これまで何度も強調してきたとおりだ。

サンプルではスタックのスクリプトに命令をもう少し追加して、起動時の作業を逐一フィールドに書き込み、ユーザーに状況を知らせるようにした(画面1)。現在何が行われているかをフィードバックすることは、利用者に安心感を与えるためにも大切である。また、万一エラーが起きた場合は、管理者はこのフィールドの情報から問題点を探ることもできる。

自作オフィスシステムを導入してしばらくは、使うたびに機能を改良したり情報を追加したくなるだろう。こういう自動更新の仕組みを活用して、どんどんシステムを充実させていきたい。

システムのモジュール化

残された誌面を利用して、システム管理者にとって考慮に値するいくつかの点に触れておく。まずはモジュール化について。

先に述べた起動専用スタックもそうだが、トータルのシステム設計を考える上で、どの機能は一つのスタックにまとめ、また別のスタックとして独立させるかという分業のプランは重要なポイントである。機能面でのグループを考えると、オフィスシステムのためには

  1. 起動作業とアップグレードを受け持つもの
  2. 基本プラットフォームとしてローンチャの役割やidleの監視を行うもの
  3. グループで情報や仕組みを共有するため、サーバーに置いた方がよいもの
  4. ユーザーが自分専用のツールとして自由に加工できるもの

の4つをあげることができそうだ。このなかでサーバー上に置く(3)は機能ごとにスタックを分割し、他はそれぞれ1つのスタックにまとめるのがよいだろう。これらの関係をまとめてハイパーカードオフィスの設計図を書いてみると、図のようになる。

このような機能に応じたモジュールによる構成は、ユーザーが仕組みを理解しやすい上に、メンテナンスが容易になるという利点もある。ただ、ハイパーカードではスタックの移動はどうしても時間がかかる(特にサーバー上のスタックは遅い)うえに同時利用が出来ないという弱みがあるので、頻繁に使う機能は可能な限りメインのスタックに組み込んでおくのがよい。

HyperCard Officeの設計図

ライブラリ機能の利用

機能を複数のスタックに分散してモジュラー構成にすると、同じコードやリソースをそれぞれのスタックが持つことになり、効率が悪い。特にどのスタックにも共通するスクリプトを一部書き換えたりすると、全部のスタックを修正するか、スタックによって働きが異なるという事態を甘んじて受け入れるかという選択を迫られることになってしまう。

こうしたことを避けるためにも、汎用のスクリプトや外部命令などをまとめたライブラリスタックを作成し、個々のスタックからはこのライブラリを呼び出して使うようにするべきである。ライブラリに収めたスクリプトなどは、最初に

start using stack "Library"

のようにしてライブラリを呼び出しておけば、あとは全く自分自身のスタックに組み込んだものと同様に利用できる(*注4)。

1995/7号では、頻繁に利用するハンドラはスタックスクリプトに置くことを勧めていたが、ここではさらに一歩進めてシステム全体での共有をはかろうというわけだ。これはまた1995/8号でとりあげた資源の抽象化とも関連する、システムを管理していく上で重要な考え方である。

汎用テキストフィルタ

最後に、管理者自身にとって便利なツールを取り上げておこう。オフィスシステムを構築して行くに当たっては、スタックの開発と並行して、さまざまな資料やデータを収集しユーザーに提供するという作業もこなさなければならない。この場合、入手したデータが共有情報としてそのまま使えることは少なく、たいていは何らかの加工やフォーマットの変換が必要になる。

これらの作業の中心となるのは、テキストファイルを読み込み、内容を1行ずつチェックしながら、何らかの目印を使ってデータを切り分けたりマークを付けたりするといったものだ。つまりはテキストフィルタとしての働きである。筆者はこうした作業のために汎用のテンプレートを用意し、内容に応じて一部を書き換えて利用している。実際、ほとんどの作業でスクリプトの基本構造は同じなので、わずかな変更で様々なファイルを加工することが可能だ。リスト3に、テンプレートを示した。これはお馴染みのHDBファイル(*注5)をタイトルと本文に切り分けていくものだが、7行目の区切り行の設定や、8〜21行のループの中身をデータに合わせて手直しすれば、幅広く応用できる。サンプルのスタックでは、テンプレートスクリプトを設定したボタンを自動作成して、スクリプトエディタまで開いてくれるもの(画面2)を用意しておいたので、利用して頂ければ幸いである。

*     *     *

この連載は、不要な機能で肥大化し、データの標準化が考慮されない市販アプリケーションから離れて、自分たちのニーズを的確に反映できる等身大のシステムを考えようとしてきた。ハイパーカードを選んだのは、手元にあるツールの中で最もその目的に近かったからだが、もちろん他のツール、例えばAppleScriptやperlを使っても多くのことは実現できるだろう。大切なのは情報そのものであり、またそれを使う我々自身の仕事や思考である。この点さえしっかり押さえておけば、必ず本当に役に立つシステムを作っていけるはずだ。皆さんのオフィスシステムのますますの発展をお祈りして、筆をおくことにする。

*注1

AppleScriptのduplicate命令を使ってFinderを操作する方法もあるが、HyperTalkから直接扱いにくい。

*注2

厳密には、すでにメモリに読み込んだオブジェクトを書き換えるとトラブルになる。したがって、ボタンを入れ替える程度なら自分自身を更新することは不可能ではないが、基本的には遠隔操作でアップグレードする方が安全である。

*注3

1995/8号で述べたように、テキストファイルにHyperTalkの命令を記述しておき、これを変数strに読み込んでdo strとしてやれば、スタックに書き込んでいない命令でも随時実行することができる。

*注4

ライブラリスタックは、一度指定するとハイパーカードを終了するまでどこからでも利用できる。ただし、利用可能なのはライブラリのスタックスクリプトとXCMDなどのリソースで、カードやバックグラウンドのスクリプトは共有されない。

*注5

1995/7号で作成したHyperDB形式のデータのこと。レコードをハイフン2つの行(--)で区切り、各レコードの最初の1行を見出しとするテキストファイルで、単純な情報を効率よく整理することができて便利。添付CD-ROMに、これまでの連載のテキストをこの形式で収録している。

リスト1

-- on startUpハンドラから呼び出す

 1: on upGrade scriptFile
 2:   put ReadFile(scriptFile) into scr
 3:   if line 1 of scr is cd fld "LastUpgrade"
 4:   then exit upGrade
 5:   do scr
 6:   put line 1 of scr into cd fld "LastUpgrade"
 7: end upGrade

リスト2

-- リスト1でscriptFileとして指定するファイル

 1: --This is the upgrade for 96.04.18
 2: global errorLog
 3: put "HyperLauncher" into xName
 4: put "Pulic:Upgrade:" into pSource
 5: put "HD:HyperCard:" into pDest
 6: FileCopy pSource & xName, pDest, TRUE -- XCMD
 7: if the result is NOT "" then
 8:   beep
 9:   put the result & return aftr errorLog
10: end if

リスト3

-- "--"で区切られたテキストファイルを処理するテンプレート
 1: on mouseUp
 2:   answer file "処理するファイルを選択"
 3:   if it is "" then exit mouseUp
 4:   put it into FilePath
 5:   put ReadFile(FilePath) into str
 6:   put 0 into status
 7:   put "--" into sepLine
 8:   repeat with i=1 to number of lines of str
 9:     set cursor to busy
10:     put line i of str into theLine
11:     if status is 0 then
12:       put theLine into myTitle
13:       put 1 into status
14:     else if theLine is sepLine then
15:       put myTitle & TAB & myText & RETURN after outStr
16:       put "" into myText
17:       put 0 into status
18:     else
19:       put theLine & RETURN after myText
20:     end if
21:   end repeat
22:   ask file "保存するファイルの名称" with lastHCItem(":",FilePath)
23:   open file it
24:   write outStr to file it
25:   close file it
26: end mouseUp

(MacUser Japan, May 1996)