FileMaker Serverのアップデータがフリーズする理由

FileMaker Server 14.0.4bのアップデータがリリースされました。このところ、アップデートが頻繁にありますが、いざアップデートしようとすると、最初の部分でフリーズしてしまうことがあります。フリーズと言っても、マウスカーソルがレインボーになってしまう現象です(画面ショットではレインボー状態は撮影できないので、以下の図は普通のポインタになっています)。

shot3215

ちなみに、この現象は、14.0.4bのアップデータに限らず、13のアップデータでも発生することがあります。もちろん、いつまで経ってもこのまま進みません。さて、なんででしょうか? アクティビティモニタを見ると、パッチアプリケーションのCPU稼働率が100%近くになっています。ということは、本当にフリーズか、適切でない処理待ちをしていることが考えられます。

そこで、ターミナルを起動して、プロセスを見てみます。パッチアプリケーションのプロセスには「Patch」という特徴的な文字があります。以下のコマンドで、プロセスIDは27530だとわかります。(以下、コマンドラインの出力が長いので折り返して見えるようにしておきますが、見づらい点はご容赦ください。)

$ ps jax|grep Patch
root 27530 1 27523 0 0 S ?? 0:15.60 /Volumes/FileMaker Server 14.0.4b Patch 1/FileMaker Server 14.0.4b Patch.app/Contents/MacOS/FileMaker Server 14.0.4b Patch

次に、このプロセスが別のプロセスを起動していないかをチェックします。すると、以下のように、「/bin/sh /Users/msyk/Library/Application Support/1358455 0」なるプロセスがあります。最後の方の数値は起動ごとに違うものがつけられ、正常終了すると消されているファイルです。

$ ps jax|grep 27530
root 27530 1 27523 0 0 S ?? 0:15.60 /Volumes/FileMaker Server 14.0.4b Patch 1/FileMaker Server 14.0.4b Patch.app/Contents/MacOS/FileMaker Server 14.0.4b Patch
root 27545 27530 27523 0 0 S ?? 0:00.05 /bin/sh /Users/msyk/Library/Application Support/1358455 0

これは/bin/shつまり引数をシェルスクリプトとして実行しているということです。catコマンドで、ファイルパスにスペースがあるのでダブルクォートで囲むなどの対処をして、中身を読んでみます。パッチアプリケーションは、このプロセスが終了するのを、おそらく単なるループで待っているためにフリーズするのでしょう。psコマンドである種のプロセスが存在するかどうかを2秒ごとにチェックし、調べているプロセスがなくなれば、スクリプトを終了します。

$ cat “/Users/msyk/Library/Application Support/1358455”
#!/bin/sh

cd /Library/Application\ Support/FileMaker/FileMaker\ Server
./launcher -stop

while [ “`ps auwwx | grep -e fmserver_helperd -e fmsib -e fmslogtrimmer -e fmxdbc_listener -e fmsased -e httpd | grep -v grep`” ] ; do
sleep 2
done

whileの行を見ると、psコマンドの結果に、fmserver_helperd、fmsib、fmslogtrimmer、fmxdbc_listener、fmsasedという文字列があるかを調べています。つまり、FileMaker Serverの様々なプロセスが起動した状態なのかを調べています。さらに、httpdというプロセスまで存在するかを調べています。アップデートは、FileMaker Serverを停止させて行うようにということで、FileMaker関連のプロセスがなくなっているという条件はまあいいでしょう。ちなみに、FileMaker Serverのプロセスを事前に全部止めておくには、以下のコマンドでできます。

sudo launchctl unload /Library/LaunchDaemons/com.filemaker.fms.plist

しかし、httpdとなると、何らかのきっかけで動かしてしまっているかもしれません。あ!そういえば、Server.appで色々試したぞと思ってチェックすると、Server.appのソフトウエアアップデート、キャッシュ、Xcode Serverあたりがhttpを使っていました。しかし、Server.appは、それらのプロセスをオフにしても、httpdの稼働を止めません。仕方ないので、sudo launchctl unload <plistファイル>で順次落として、やっとFileMaker Serverのアップデータが動くようになりました。ちなみに、こうしたデーモンは、launchctlで起動しているので、killしてもすぐに再起動されます。そこで、/System/Library/LaunchDaemonsや、/Library/LaunchDaemonsに該当するファイルを探すわけですが、Server.appについては、/Applications/Server.app/Contents/ServerRoot以下の、/System/Library/LaunchDaemonsや、/Library/LaunchDaemonsにあるplistファイルを利用してデーモンを起動しています。これらのファイルから該当するhttpdを起動しているものを探して落とさないといけません。チェックすべきplistファイルのある場所は文中に記載しましたが、見づらいでしょうから以下に列挙します。

/System/Library/LaunchDaemons
/Library/LaunchDaemons
/Applications/Server.app/Contents/ServerRoot/System/Library/LaunchDaemons
/Applications/Server.app/Contents/ServerRoot/Library/LaunchDaemons

しかし、一番の問題は、「httpdが起動していたらアップデートをしない」という仕様です。つまり、結果的にFileMaker Server以外のhttpdの起動を許さないという仕様に問題があります。Server.app自体が色々なサービスでhttpdを使うのですが、80番ポートの取り合いになるのは確かにまずいでしょう。しかしながら、FileMaker Serverのインストーラーは、自分自身のhttpdのポート番号を指定することで、他のサービスとの同居の可能性を探っています。しかし、このスクリプトを見る限りは、「FileMaker Serverが起動したhttpd」ではなく、単に「名前がhttpd」のプロセスを探しているにすぎません。つまり、FileMaker Server以外でhttpdを使いっていればトラブルが発生する仕様なのです。これでは仕様の上で矛盾があると言えるでしょう。

もちろん、特定のサーバーではFileMaker Serverしか動かさないという前提でもそれはそれで構わないと思いますが、だったら、LinuxのVMで動かすようにして欲しいというのが総意ではないでしょうか。OS XとWindowsで、アプリケーションみたいなインストーラでセットアップするサーバーはもはや古さを感じます。現在のシステム構築環境にマッチしない仕様を早く改善しないと、先頭集団からさらに引き離されるでしょう。

FileMakerのWebビューアが、WebDirectで文字化け

最近ブログ更新していないので、小さなネタですが書いておきます。私がWebDirectの話をするのは予想外かもしれませんが、ちょっとハマったことがあったので書いておきます。FileMakerでのソリューション内で、複数の文書を並べるような機能が必要だったので、Webビューアを使いました。全文字を平面上に成り行きでレイアウト出来るので便利です。Webビューアには、dataスキームを利用して、フィールドの値などを合成したHTMLを与えてWebビューアに表示しました。FileMaker Pro上ではもちろん問題ありません。しかし、WebDirectでWebビューア部分が文字化けしました。理由はフォントではなく、文字セット指定がなかったからです。そこで、

data:text/html;charset=utf8,<!DOCTYPE html><html><head>
<meta http-equiv='X-UA-Compatible' content='IE=Edge,chrome=1'/>....

のように、charsetを入れればブラウザ上では文字化けは無くなりました。charsetを省略すると、us-asciiと同じになるそうですが、それはブラウザ上だからかと思われます。FileMaker Proでは指定なしでも文字化けないようにしているということでしょうね。

FileMakerのスクリプトで実現するインジェクションもしくはアスペクト指向

アスペクト指向プログラミング(AOP)はオブジェクト指向の世界での手法の1つですが、FileMakerでのスクリプトでそれを実現する方法が見つかったので、記事で残しておきます。AOPについては後ろの方でまとめて、まず、何を実現したかを具体的に説明しましょう。

マスターテーブルからの選択結果を記録する

データベースに次のようなリレーションシップを定義しています。フィールドmemoとtermはテキストで、後のフィールドは数値型です。_idの付くフィールドは連番数値を自動入力して、主キーフィールドととします。

shot3094

あるレイアウト(User Inteface)は、テーブルオカレンスのUI_Mainのレコードを表示させるように定義しました。そして、リレーションシップの先の2つのテーブルオカレンスを、3つのポータルに表示しています。このデカルト積を使うリレーションシップにより、Selectionsテーブルのすべてのレコードがポータルに表示されます。FileMaker 13からサポートされたポップオーバーボタンで選択入力をするときに、このようなリレーションシップを利用するのが1つの典型的なパターンではないでしょうか? ポータルには3つのボタンがありますが、それぞれ概ね同じ目的です。例えば、最初のポータルでは、ポータル内でのボタンを押したレコードに対応するselection_idフィールドの値が、select1フィールドに入力されます。その動作を3通り考えることで、AOPに迫るというのが概要です。当然、実際のソリューションでは主キー値となる連番はユーザーに見せないように作りますが、ここでは動作が一目瞭然となるように意識的に通常のソリューションでは見せない内容をレイアウトに表示して動作をチェックします。Memoフィールドの左側のClearボタンにより、Memoフィールドの文字列を消去します。

shot3123

ここでSelectAボタンがどうなっているのかを説明しましょう。SelectAボタンは一番簡単なというか、理解しやすい方法です。以下のように、ボタンをクリックすると、「Select Button 1」というスクリプトが実行されます。2つ目のポータルのボタンは「Select Button 2」、3つ目のポータルでは「Select Button 3」というスクリプトが動くように指定をします。ボタン名の番号と、スクリプト名の番号は対応していません。ちょっとわかりにくいことをやってしまってごめんなさい。

shot3124

3つのスクリプトは以下のようになります。つまり、ポータル内で選択したレコードのselection_idの値を、UI_Mainテーブルオカレンスのselect*フィールドに代入をしています。それぞれ、自分自身のポータルと、対応するUI_Mailのフィールドがスクリプトの設定に見えています。

shot3129

shot3130

shot3131

スクリプトの共通化

このような「同じようなスクリプト」は、共通化したいですね。昔のFileMakerなら、共通化は難しい上に、個別に記述できるから分かりやすいといった議論もあったわけですが、今時の複雑なソリューションでは、スクリプトの数が爆発する傾向にあり、1つのスクリプトにまとめる意義は高まっていると言えるでしょう。そういうわけで、「SelectB」ボタンでは、SelectAボタンの手法を1つのスクリプトにまとめてみました。3つのポータルにある各SelectBボタンは、「Select Button B」という共通のスクリプトを呼び出しています。

shot3125

この時、最初のポータルのSelectBボタンは、スクリプト引数として、次のような設定を行います。つまり、値を入力するフィールド名と、値を取り出すフィールド名を、改行で区切って指定をしておきます。それぞれのポータルのSelectBボタンは同一のスクリプトを呼び出すものの、スクリプト引数を異なるものにするということです。

shot3127

Select Button Bスクリプトは、次のようなものです。引数から値を取り出したものは、フィールド名の文字列です。その文字列のフィールド名で指定したフィールドに値を設定するには「フィールドを名前で設定」スクリプトを利用します。そして、文字列で与えたフィールドから値を取り出すのは、GetField関数を使います。引数を変数に入れると同時に、スクリプトステップは異なるものとなり、関数の利用も行わないといけません。

shot3132

共通化したことによるデメリット

ここまでのような単純なスクリプトで済ませられるのであれば、それはそれでいいのですが、実際の開発では複雑な要求が発生します。ここまでは、選択ボタンは同じ動作をするという前提でしたが、現実にはそういうことはあまりありません。ボタンごとに固有の要求が出てくることがあります。具体例としては次のようなことです。

  • あるポータルでのボタン選択をするときにだけ、別の選択肢は空欄にしたり、場合によっては初期値的な設定を強制的に行う必要がある
  • ある選択の場合に、ある条件が成り立つ場合にだけ、選択していいかどうかをダイアログで問い合わせる
  • ある選択肢の選択後に、テーブルの更新など、その選択肢に固有の処理を追加しないと要求が実現できない

こうなってくると、「そら見たことか、スクリプトはボタンごとに設定するのが王道だ」と思わず口走ってしまうかもしれませんが、未だに1ファイルに1データベースみたいな作り方をする発想が抜けきれないとしか言いようがありません。ここの例では、共通なステップは1つだけですが、複雑な処理は共通化しておかないとデバッグやメンテナンスコストが増大するのは言うまでもなく、システム構築の常識です。

もちろん、FileMakerでは、プログラミング言語的な柔軟性を犠牲にする分、ツールを使った開発がやりやすいとか、学習コストが低いという長所を得ています。しかし、なんとかならないかとも考えるわけです。

以前だと、「共通部分があるものの、違う部分もある」という場合にどういった手法をやっていたかといえば、まずは、スクリプトが分かれてしまうのは仕方ないとして、共通部分を「スクリプトの実行」ステップで呼び出すということです。もちろん、この方法は汎用的かつ共通部分の抽出ができるという面ではメリットですが、「違う部分」が発生するごとにスクリプトが増えることになります。また、ありがちですが、「違う部分がない」にもかかわらずスクリプトが別々とか、「違う部分がある」のにシステムの全然違う箇所からスクリプトを共通に使うなどの、後からの不具合発見を阻害する作りに往往にしてなりがちです。

1つの苦肉の索は、共通のスクリプト内に、IF〜ELSE IF〜END IFを利用して、例えば、押したボタンごとに分岐を作り、ボタンごとに違う処理を組み込む方法です。これだと、1つのスクリプトで共通に使えますが、一方で、ボタンが増えればIFの分岐が増えてしまいます。もちろん、ちゃんと作れば動作しますが、あるボタンの動作を追う時には無視するスクリプトが大量になってしまうなど、可読性が低くなります。また、自分が関係してるところだけをちゃんと書けばいいということは理屈の上では成り立つことですが、現実には変数を共通に使ったことでのバグの発生などが懸念されます。分離されていないことでの気づかない悪影響は、当然ながら気づくののコストがかかります。したがって、IFで分岐を入れるのはいいような悪いようなということになります。

共通スクリプトと個別スクリプトの分離

そこで、オブジェクト指向の世界でのDI(Dependency Injection)の手法により、関心ごとを分離して実装することができないかと考えました。例えば、ボタンごとにニーズが違うのであれば、ボタンごとに関心ごとが異なると位置づければ、これはAOPの実現でもあります。

まず、レイアウト上にある「SelectC」ボタンは、いずれも、「Select Button C」スクリプトを呼び出すようにしています。3つのポータル上のいずれも同様な設定になっています。

shot3126

以下のスクリプト指定は、1つ目のポータルのSelectCボタンのものです。スクリプト引数はSelectBボタンと同様な指定です。スクリプトは同一でも、ポータルごとに、設定するフィールドやポータルが参照するテーブルオカレンスが違うので、それらをスクリプト引数で指定をします。

shot3128

そして、「Select Button C」スクリプトは次のようなものです。コメントの「前処理スクリプトの呼び出し」部分が追加されています。「URLを開く」ステップと併せて示します。

shot3133

shot3108

ここで、このボタンをクリックしたスクリプトの関心ごとを、選択した結果を保存するフィールドで区別するということを考えます。この前提が上記のスクリプトの動作に必要となります。

ここで、例えば、1つ目のSelect3ボタンをクリックしたとします。すると、「Select Button C」スクリプトの最初の2つのステップで、次のように変数が設定されます。

  • $destField ← UI_Main::select1
  • $srcField ← UI_First_Selections::selection_id

そして、「URLを開く」オプションで、次の方なURLが生成されて、そのURLを開こうとします。FileMakerのURLスキーマは、ご存知ない場合には、どこかのサイト等で調べてください。

fmp://$/AOScriptTest?script=SelectButton_UI_Main_select1&param=any_parameters&$srcField=UI_First_Selections::selection_id&$destField=UI_Main::select1

最初の$で自分自身を参照します。URLのscriptパラメータは、その直前のscriptName変数の計算式をみてください。スクリプト名は、「SelectButton_<値を設定するフィールド名>」となります。値を設定するフィールド名は、ボタンのスクリプト呼び出しのスクリプト引数で指定されています。なお、コロンがフィールド名に含まれますが、無難にするためにアンダーラインに置き換えます。つまり、1つ目のポータルのSelectCボタンをクリックすると、自分自身の「SelectButton_UI_Main_select1」スクリプトを呼び出すということになります。ここで、「スクリプトの実行」ステップが使えない理由は、そのステップではスクリプトの選択はできても、変数等でのスクリプト名の指定ができないからです。なので、ここではURLスキームの利用を行います。「SelectButton_UI_Main_select1」スクリプトは例えば、以下のようなものを作成しました。select2とselect3フィールドを空白にします。ここで、レイアウトを指定する必要がない点は注目点の1つです。

shot3114

2つ目のポータルのSelectCボタンを押した時に呼び出されるURLでは、スクリプト名は「SelectButton_UI_Main_select2」となりますが、このためのスクリプトは作っていません。つまり、2つ目のポータルのSelect3ボタンをクリックした時、「URLを開く」では存在しないスクリプトをパラメーターに指定します。しかしながら、エラーとして出ないように「エラー処理」ステップを入れているので、要するに、存在しないスクリプトを実行しようとしても、スルーするだけです。

「SelectButton_UI_Main_select3」スクリプトは次のようなものです。SelectButton_UI_Main_select1スクリプトとSelectButton_UI_Main_select3スクリプトの最初の1行は同じで、パラメーターに指定した内容をmemoフィールドに入力することです。式が途中で切れていますが、結果を見れば明白だと思うので、式はここには記述していません。

shot3134

選択した時の動作を確認する

実際に動かしてみます。まず、Clearボタンを押してmemoフィールドを空白にして、3つ目のポータルのSelectCボタンをクリックしてください。すると、選択結果がselect3フィールドに入り、memoには何かの表示が見えています。つまり、Select Button Cスクリプトがボタンクリックにより呼び出され、その中で、SelectButton_UI_Main_select3スクリプトが呼び出されたということです。

shot3136

Clearボタンを押してmemoフィールドを空白にして、2つ目のポータルのSelectCボタンをクリックしてください。すると、選択結果がselect2フィールドに入りますが、memoは空白のままです。つまり、Select Button Cスクリプトがボタンクリックにより呼び出されただけの結果になります。

shot3137

Clearボタンを押してmemoフィールドを空白にして、1つ目のポータルのSelectCボタンをクリックしてください。すると、選択結果がselect1フィールドに入り、select2とselect3は空白となり、memoには何かの表示が見えています。つまり、Select Button Cスクリプトがボタンクリックにより呼び出され、その中で、SelectButton_UI_Main_select1スクリプトが呼び出されたということです。

shot3138

Select Button Cスクリプトでは、IF〜Else IFを使うことなく、クリックしたボタンに応じて処理を分岐させています。ここで、もし、新しくselect4フィールドを用意して、同様にポータルから選択できるようにしたとします。もちろん、ボタン等にSelect Button Cスクリプトを設定して、引数にフィールド名を指定します。そして、select4フィールドに特有の処理を、「SelectButton_UI_Main_select4」を記述して追加します。ここに、選択肢を設定する前に行いたい処理を記述します。こうして、フィールドが増えてスクリプトの利用元が増えたとしても、Select Button Cスクリプト自体に一切の変更を加えることなく、select4フィールド特有の処理を追加できることになります。実装のパタンとしては、GoFのパターンのStateに近いことをやっていると考えていいかと思います。

実開発への展開に向けて

まず、FileMaker的な考慮点を考えましょう。ポイントとなるのは、fmp://$/… スキームにより、変数で与えたスクリプト名で実行できる点です。この時、本当に通信するのではなく、同一のスクリプト実行環境で実行を行っているようです。その証拠として、「URLを開く」ステップの先で、「全スクリプトの終了」ステップを実行すると、呼び出した元のスクリプトも途中で中止してしまいます。また、このことは、「URLを開く」ステップの先で呼び出したスクリプトで、状況を判定して、これ以上の処理はキャンセルするという動作を組み込むことができることも言えるのです。また、グローバル変数を「URLを開く」ステップの先で設定して、それを呼び出し元でも参照できます。つまり、同一のグローバル変数が使えるので、「URLを開く」ステップは同一のユーザーセッション上で稼働していると言えるのです。この辺りの検証スクリプトの残骸が、コメントで残っているので、参考にしてください。

ここのスクリプトでは、前処理だけを実装しましたが、後処理、あるいはある特定の「中処理」を必要に応じて組み込むことも可能です。これは、呼び出すスクリプトの性質上、自由に決めることができるでしょう。一方、FileMakerの場合、その「仕様記述」に困難さんがある点も見逃せません。コメントに書くというのは曖昧かつ、記述者により違いや間違いの混入など、問題点は多いでしょう。開発のマネージメント上、状況に応じたベターな方法を見つける必要があります。

アスペクト指向スクリプトプログラミング

アスペクト指向とは、オブジェクト指向でのクラスの考え方では解決しにくい問題を扱います。クラスは単一の仕組みを持つのが理想ではありますが、いろいろな機能を組み込んだ結果、幾つかのクラスに共通の処理を実装してしまったというようなことがあるかもしれません。機能の実装においては、ある基準でまとめた結果、別の基準で見た時にはまとまってないということがあります。よくあるのがログ記録機能です。いくつかのクラスの実装ではログの記録があるものの、そのログの処理はクラスが違っても共通のことです。そうであれば、ログの記録ということ自体をその他のクラスとは別の独立したことと考える方が、明確にその機能だけに集中して検討が可能です。つまり、物事のある側面(Aspect)に注目すると、その側面は必ずしもクラスとしての分解に馴染まないことが出てきます。しかしながら、側面として検討した昨日をうまく実装する方法が必要になります。それがアスペクト指向プログラミングです。

一方で、アスペクト指向はオブジェクト指向を否定するものではなく、オブジェクト指向プログラミングの拡張の1つとして捉えるべきです。ただし、オブジェクト指向ではないプログラミングでも適用できる手法です。その代表的な実装方法がDIであり、DI(Dependency Injection)はプログラムのあるポイントに別のプログラムを挿入することです。ただし、オブジェクト指向の世界においては、インタフェースや抽象化クラスなどのいろいろなテクニックを使って、実装上の振る舞いや制約をきちんとしたルールに落とし込んでいると言えます。ある側面を定義したものをDIによって別のクラスに埋め込みをするということでの、アスペクト指向の実現できているということになります。アスペクト指向とDIは同一のものではありませんが、結果的には表裏一体な関係であると言えるでしょう。FileMakerでのInjection、つまり処理の注入は、若干明示的にはなってしまいますが、「URLを開く」でできることが以上のようにわかりました。しかしながら、あえてタイトルにインジェクトションだけを書いたのかというと、依存性つまりDependencyのコントロールが事実上できないという点があります。1つの分かりやすい側面は、名前さえ一致すればどんなスクリプトも呼び出せてしまうという点は、依存を無視しているともいえるわけです。

ここで示した例は、スクリプトにより選択肢の選択ができるという共通点があります。その意味では、Select Button Cスクリプトが1つのクラスだと思っていいかと思います。一方で、選択する先によって関心事が違うという状況を想定しました。つまり、あるボタンは「別のフィールドも更新する」という側面を持ち、別のボタンは「他には何もしない」という共通点の薄い別の側面があったわけです。しかしながら、「URLを開く」を応用した手法により、ボタンごとに異なる側面の実装を独立したスクリプトできるようになりました。したがって、この手法は、FileMakerのスクリプト実装におけるアスペクト指向プログラミングであると言えます。

FileMaker Server 14をOS Xで稼働するときのWebのカスタマイズ

以前に、FileMaker Server 13とOS X ServerのWebという文書で、FileMaker ServerのWebを動かすための方法を書きましたが、そこで、.htaccessファイルなどを有効にする方法記述しました。しかしながら、FileMaker Server 14.0.4を新たにインストールした場合、前記の文書の記述だとエラーが出ることがわかりました。この点は、FileMaker Server 14のどのバージョンでも当てはまるようです。

ということで、設定ファイルはHTTPServer/conf/httpd.confは以下のように変更すれば良いでしょう。

<Directory "${HTTP_ROOT}/htdocs">
    AllowOverride All
    Options All -Indexes -ExecCGI -Includes
    Require all granted
</Directory>

FileMaker Server 13のとき、「Order allow,deny」「Allow from all」も、Directoryタグ内に書いていたのですが、これを書くと、こんなエラーが出ました。最初のエラーにより、ステータスは403が返り、もちろん、ブラウザでは何も出てきません。後半の「an unknown filter was not added: includes」のエラーは派生的なもの、あるいは副作用的なもののようです。

[Sun Nov 29 01:00:40.179248 2015] [authz_core:error] [pid 1534] [client 219.121.7.182:38310] AH01630: client denied by server configuration: /Library/FileMaker Server/HTTPServer/htdocs/index.php
[Sun Nov 29 01:00:40.179642 2015] [core:error] [pid 1534] [client 219.121.7.182:38310] AH00082: an unknown filter was not added: includes

それから、ディレクトリへのアクセスで、index.htmlよりも先にindex.phpを開きたい場合のDirectoryIndexディレクティブの設定は、上記のDirectoryタグのすぐ下にあるdir_moduleが組み込まれた場合の設定にあります。しかしながら、ここを変えても意図通りに動かないなと思ったら、/Library/FileMaker Server/Web Publishing/publishing-engine/php/yosemite/httpd.fmi.conf.phpの最後の行にあるDirectoryIndexディレクティブを修正しないといけないことが分りました。

Apacheの設定ファイルは、バージョンが違うとそこそこ違ったりしますし、管理手法も比較的変動が大きく、「以前使えた設定や手法が通用しない」ということはこのところ頻繁に経験します。注意しましょう。

実は深刻な“カミFileMaker問題”

(2015/2/12 0:28更新:Facebookでの杉原さんの意見も反映させました。2015/2/13 17:00更新:Facebookでの日高さんの意見も反映させました。ありがとうございます。)

ネ申ExcelはExcelだけの問題か?

Excel方眼紙や罫線優先のワークシートなどなど、Excelで作った文書のうち、見栄えを整えることを主眼として作ってしまったことにより後からデータの活用ができなくなってしまった文書などを「ネ申Excel」と総称されています。三重大学の奥村先生の論文にまとめられています。良し悪しの問題は難しいのですが、例えばネ申Excelな記入用紙はWebフォームにすれば、即座に一覧が作られるなど、より利便性が高い代替え手法が明らかに存在するような場合があります。そのようにExcelにこだわる余り、自身の効率化を損なうのはもちろん、入力をするなどの利用者の利便性を著しく損なう状態になるのは避けるべきだと言えるかと思います。

同じような問題は他のソフトウエアにも、サービスにも存在します。ここで、データベースソフトの話をしたいのですが、そうなると、AccessかFileMakerかということになります。自分自身の問題でもあるので、馴染みの深いFileMakerを取り上げ、「カミFileMaker問題」として扱います。あえて、カタカナの「カミ」にしたのは、大昔「ファイルメーカー」と呼んでいたFileMakerへのトリビュートです。FileMakerのレイアウト機能は、帳票を高い自由度で作成できることから、従来の紙ベースで行われてきた業務をそのままデータベース化できる強い動機付けになっています。同じような仕様がAccessにもあることはありますが、プロの開発者からデータベース利用者までがみんなしてテーブルを定義してレイアウトをいじるというのはFileMaker市場の大きな特徴だけに、「カミFileMaker問題」が浮き彫りになると考えられます。

「カミFileMaker問題」とは?

ここで問題の定義として、紙の帳票類をそのままデータベース化してしまうことで発生する問題とします。もちろん、帳票をそのままデータベース化するだけでも、例えば、共有ができることや、印刷を省きパソコンやタブレットで閲覧することでの即時性などのメリットは発生します。最初の帳票ができたとき、「これはいい!」と誰もが思います。だけど、いくつも帳票を作るに従って問題が顕在化します。

紙が画面に変わっただけ?

帳票をデータベース化すると、どうしても従来のワークフローが結果的に踏襲されることになります。むしろ、ワークフローは出来上がっているのだから、それを電子化すればよりスムーズという、あまり根拠のない理屈を信じて突き進みます。その結果、まず、電子化されているのに「転記」という作業や、帳票の生成や破棄、あるいはステータス更新という動作に「手作業」が入ってしまいます。今までは紙だったので、それはやって当たり前でした。しかしながら、電子化するときに、そこでの自動化を深く考えなかったとしたら、同じことを端末を操作してやらないといけません。パソコンを扱うのが弱いとか、ストレスが高い人は、そこでまずはつまずくことになります。

紙にはなかったリンク情報はどうなった?

それでも仕事をみんなでがんばってこなしたとします。そして、さまざまな帳票レコードが、1つのエンティティに対して複数積み重なることにより、新たな問題が発生します。ある帳票と別の帳票が結びついている場合はよくあります。1対1や1対多ということもあるでしょうし、多対多もあります。紙で作業していると、その結びつきを人間がやっていることがあります。業務上の常識から、誰もが自動的に異なる2枚の帳票に関係がある、関係ないということを判定できるのです。この作業をパソコンの画面上で人間が行うのは非常に面倒です。紙のファイルを何冊か机に並べて対応するものを開けて突き合せるような手軽さは、今のパソコンやタブレットではまだまだ無理です。

もちろん、相手の文書IDを記録するなどすればいいのは当然ですが、気付いた時には遅かったということもあります。また、そのような「リンク」の重要性が、問題が発生しても気付かない、あるいは気付かないふりをするということあるでしょう。かくして、対応する文書の手がかりをかなり強引に引っ張り出すことになります。「同一顧客で、この帳票より前のもののうち、最新のもの」などといったリレーションシップを組むなどします。それでも、運用は可能かもしれませんが、対応が取れなくなる可能性が0ではなく、小さいながらも0%よりも大きくなります。また、業務で発生するイレギュラーなケースを忘れていると、ミスにつながります。ビジネスロジックでほぼ解決できるものでも、より単純な解決法があるのなら、単純な方が安定しているのは言うまでもありません。

矛盾する2つのフィールドの関係

さらにこんな例もあります。紙の帳票から、別の帳票に転記するとき、人間が転記するといいように解釈していたのですが、それを電子化すると、機械的に転記できないような場合が発生します。つまり、それぞれの帳票のスキーマに、論理的な不一致が発生してしまうのです。もっとも身近な例では、入力帳票が「氏名」で、それに対応する別の帳票が、姓名別々のフィールドのような場合です。こうしたスキーマの不一致は、紙の帳票をそのままデータベース化すると、気が付いたら行っていたということになります。また、転記なのか参照なのか、ここの考え所を全部転記することにしてしまったことで、かえって手作業が増えることもあります。

この問題は、突き詰めると、データベースのスキーマを検討するときに必ず必要となるその業務ドメインのモデル化が不正確なのです。フィールドとテーブルを定義すれば良いというのはFileMakerの機能のことで、設計者は他に考えないといけないことはたくさんあります。データ間の連携はもちろんだし、これについてはリレーションシップで定義することになります。しかしながら、FileMakerの機能に見えないこととして、あるデータは転記して見えるようにするのか、参照して見えるようにするのかということを考える必要があります。これは、FileMakerのテーブル設計のダイアログボックスでは明示化されていないものの、極めて重要な設計上の決まりごとになります。

データベースには、データベースに合った設計を

こうした問題は、昔からありますが、FileMakerは手軽だからこそ、陥る罠でもあるといえます。あえて、「カミFileMaker問題」として、問題を浮き彫りにすることで、より多くの方が意識できるようになればと考えました。もちろん、プロの方々もこうした失敗を重ねてきていて、いろいろなノウハウをお持ちでしょうし、長年使ってきた人も同様です。例えば、受託開発のとき、導入経験がないお客さんの要望をそのまま構築すると、「カミFileMaker問題」の宝庫です。プロや熟練者は、そこでしっかりとお客さんの要望を受け入れつつ、問題の発生を抑える手立てを考えないといけません。言われた通りにやればいいというのは間違いで、そのようなやり方を続けてきた結果使われないシステムを納品することになり、信用を落とすことになるのです。この問題を認識し、きちんと説明して方向付けをする必要があるのは、プロや熟練者の皆さんなのです。決して、素人を茶化すための問題定義ではないことは最後に強調したいと思います。

以下にまとめておきます。もちろん、みなさんの意見や表現の向上も大歓迎です。

「カミFileMaker問題」の発生

  • 帳票類をそのままFileMakerのデータベースで再現する電子化

「カミFileMaker問題」による起こりがちな結果

  • 一見すると効率化されたように見えるが、帳票作業とは異なる事務作業等が増えているなど、実は効率化されていない
  • 機械的に行えるデータの連携や解釈などが、データベースの仕様に含まれず、そうした作業も人間が行う必要がある
  • 2種類の帳票でスキーマが異なり、論理的には転記ができず、人間が解釈してつどつど修正しないといけなくなる
  • 紙が減ることの効率性だけに注目した結果、システム運用コストに気が回らず、気が付いたらかえってコスト高になってしまっていた
  • データベーススキーマの設計において正規化という点が考慮されず、データ解析に支障をきたしたり、あるいは解析自体が不可能な、品質の低いデータを蓄積してしまう。

「カミFileMaker問題」の本質

  • コンピュータ作業に最適なワークフローを検討し、転換しないために、結果的にさほどの効率化もされない
  • データ間のリンク構造を記録できないスキーマ上で、ビジネスデータが蓄積され、どうしようもなくなり、最悪はデータ活用に制限が出てきてしまう
  • データベースのスキーマを単に「紙にあった項目」のみで認識することで、ドメイン自体を表現するモデルの精度が低くなってしまう

FileMaker 13で、XMLおよびXSLTによる出力

久しぶりにタイトルのような事をやりました。この記事のハイライトは、変数でXSLTファイルの位置を指定できるようになったものの、エラーが出るという事象に遭遇しますが、その対処方法が分かったということです。

XML出力は、FileMaker 5くらいからありますし、出力するXMLデータにXSLTを適用して、テキストやらHTMLやらを生成することができるので、ちまちまと文字列処理を書かなくてもいいので便利です。XSLTの習得が大変という話もありますが、今時この種の情報は「基本知識」でしょうから、勉強すればいいのです。私自身は幸いにも、今はなくなってしまったXSLTでのWeb公開の時代に、かなり勉強していたし実稼働させたソリューションもあったので、自分的にはXSLTはOKです。この記事では、XMLやXSLTあるいはそれらを利用するFileMakerの機能については詳細には説明しませんので、必要な方は予習をしてください。

現実にXML/XSLTを使うとき、当然ながらXMLはテーブルを出力するときのフォーマットなので、テーブルから生成されることになります。一方、XSLTはどうでしょうか? 確実は方法は、Webサーバ等に配置して、URLで指定することですが、データベースファイルと別の管理対象ができて不便です。そこで、XSLTのテキスト自体をテーブルのフィールドにテキストとして保存しておくことで、データベースと一体化して管理ができて便利です。ただし、そのXSLTのテキストを利用するときにはファイルにしなければなりません。現実にはスクリプトを組むとして、1フィールド、1レコードだけのタブ区切りで出力すれば、余計な “” などは含まれません。ただし、その1フィールドに、改行が入っていると、コード番号12のものに置き換えられます。後から変更するのは面倒なので、XSLTのテキストから改行を除去する計算式を設定した計算フィールドをエクスポートすればいいのです。もちろん、XSLT内では改行の有無で動作が変わらないにしなければなりません。

さて、そこで、このXSLTファイルをどこに保存するのかということですが、WindowsでもMacで稼働できるようするには、テンポラリフォルダがいいのではないでしょうかということで、次のようなスクリプトで変数にパスを入れることにしました。順当な方法かと思います。

スクリーンショット 2014-06-26 10.47.20

この変数$templateJの結果を利用して、XSLTのテキストをエクスポートします。前に説明したように、スクリプトで、1レコードのみを対象レコードとして、改行を省いたテキストのフィールドだけをタブ区切りで出力します。出力ファイルに、変数$templateJを指定します。

ここで、XSLTによる変換をスクリプトのどこかで組み込むとします。スクリプトステップの「レコードのエクスポート」で、「出力ファイルの指定」を行い、OKボタンを押すと、ファイルタイプが「XML」の場合はさらに次のダイアログボックスが表示されます。ここで「XSLスタイルシートを使用」を選択し、ファイルを指定するわけですが、「ファイル」だとダイアログボックスが出て来て、特定のファイルの指定が必要です。Get ( テンポラリパス ) は一定のパスではない模様ですし、Win/Macでパスは違います。なので、「計算」を選択して、前の変数$templateJを指定して、実際に動かしてみます。ボタンと計算式の文字列が重なっているところにFileMaker社のこの機能への姿勢が見て取れます。

スクリーンショット 2014-06-26 10.46.40

すると、XMLのエクスポートをするときに、次のようなエラーが出ます。SAX(XMLのパーサ)のエラーがそのまま見えていて意味が分かりにくいですが、ようするにファイルが見つからないということです。Windowsでは、実際に見つからなかったパスも見えています。

スクリーンショット 2014-06-26 10.49.33

変数$templateJで出力し、その直後に変数$templateJでファイル参照して見つからない。ようするにバグなのですが、バグで使えません、以上ということでは前に進みません。バグは直らない可能性もあるからです。

そこで、変数$templateJの内容を、MacとWindowsで調べ見ました。Macだと、「/Macintosh HD/var/tmp/….」みたいになっています。Windowsだと、「/C:/Users/msyk/….」となっています。まず、Macは、明らかにパスの最初のコンポーネントを取り去れば、存在可能なUNIXパスになります。Windowsは…ともかく、まず、XSLTのテキストをエクスポートした後、以下のような「変数を設定」スクリプトステップを追加して、最初のコンポーネントを省いてみました。

スクリーンショット 2014-06-26 10.46.58

Macでは、予想通り、それでエラーなく動きました。一方、Windowsは別の対策をしないといけないかと思ったのですが、なんと、ちゃんと動きました。UNIXみたいなパスの与え方でどうやら動くようです。

XSLTのTipsを少し書いておきましょう。関連レコードのフィールドは、TOさえあれば出力できると思っていたら、ポータルに展開しないと出力されません。ポータルがない場合は、ちゃんと警告メッセージを出して、最初のレコードの値だけが出力されると言われます。ということで、ポータル作成はさぼれません。

関連レコードのデータは、たとえば2つのフィールドがあるとして、関連レコードが3つあると、次のように出力します。このノードの上位ノードのタグはROWになります。

<COL><DATA>1</DATA><DATA>2</DATA><DATA>3</DATA></COL>
<COL><DATA>abc</DATA><DATA>def</DATA><DATA>ghi</DATA></COL>

上記の2つのフィールドの番号を1、2とします。ROWタグがカレントノードのとき、上記のデータを展開するのにfor-eachを使うのですが、同じポータルにある関連レコードがいくつかるとき、for-eachをそのうち1つのフィールドに対して行います。次のような感じです。ネームスペースの略号は、xsl、fmrとしています。

<xsl:for-each select="fmr:COL[1]/fmr:DATA">
    <div>
        <xsl:value-of select="." />
        <xsl:value-of select="../../fmr:COL[2]/fmr:DATA[position()]" />
    </div>
</xsl:for-each>

最初のfor-eachは普通にDATAタグが複数あるので、それを1つ1つ取り出します。3行目の「.」によって、1つ目のフィールドの現在のDATAのテキストを取り出すので、「1」「2」「3」という値が順次取り出されます。2つ目のフィールドは、4行目にあるように、XPATHの記述で、カレントノードからROWまで「../..」でさかのぼり、そこから、COL、DATA集合へと下ります。そして「position()」というのは関数です。for-eachでループしているときに、何番目なのかを示す値を返します。これで、「abc」「def」「ghi」という文字列が順次得られます。

最後に大サービスで(笑)、FileMakerのXML出力向け(ただし、FMRXMLRESULTスキーマ)の汎用的なテンプレートを書いておきましょう。コピペして、あとはデータの順序に合わせてFMPXMLRESULTやROWタグ要素に対応するテンプレートにHTML等で出力テンプレートを書くだけです。

<?xml version="1.0" encoding="UTF-8"?>

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    xmlns:xhtml="http://www.w3.org/1999/xhtml"
    xmlns:fmr="http://www.filemaker.com/fmpxmlresult"
    exclude-result-prefixes="xhtml fmr">
<xsl:output encoding="UTF-8" method="xml" indent="yes"
   omit-xml-declaration="yes"/>

<xsl:template match="fmr:ERRORCODE | fmr:PRODUCT | fmr:METADATA">
</xsl:template>

<xsl:template match="fmr:FMPXMLRESULT">
    <html><body><table>
       <tr><th>Name</th><th>Activity</th></tr>
       <xsl:apply-templates />
    </table></body></html>
</xsl:template>

<xsl:template match="fmr:ROW">
    <tr>
        <td><xsl:value-of select="fmr:COL[3]/fmr:DATA[position()]" /></td>
        <td>
            <table>
                <xsl:for-each select="fmr:COL[1]/fmr:DATA">
                   <tr>
                       <td><xsl:value-of select="." /></td>
                       <td><xsl:value-of select="../../fmr:COL[2]/fmr:DATA[position()]" /></td>
                   </tr>
                </xsl:for-each>
             </table>
         </td>
    </tr>
</xsl:template>

FileMaker Server 13トラブル対策メモ

Mac OS X Mavericks+Server v3上で稼働させているFileMaker Server 13が、再起動後ちゃんと動かなくなりました。トラブル対策をして動くようになったので、「今度また再起動したとき」に慌てないように、メモっておきます。

そもそも、あるデータベースに対して、スケジュールでスクリプトを動かそうとしたのでした。そうしたら、正しいアカウントで認証しても実行できるスクリプトがないと言われました。そんなはずはありません。他のパネルを見てみると、公開しているデータベースの一覧には何も出ていないのに、FileMaker Proからはデータベースを開くことができます。つまり、一覧がおかしいということでしょうか。ここで、Admin-Console再起動をするか、サーバの再起動をするか、非常に迷ったのですが、いろいろあってサーバの再起動をしました。正確には、30分待っても落ちなかったのでディスクアクセスをしていないタイミングでリセットしました。

その後、起動はして、FileMaker Proからのデータベース接続はできましたが、Admin-Consoleは開かず(ログインパネルすら出ない)、そしてWeb公開も失敗しています。Webサーバのデーモンhttpdが1つも上がっていない。

まず、やってみたのは、以下のコマンドの入力です。Admin-Consoleにログイン可能な管理アカウントは、ユーザ名がadmin、パスワードはpassword(もちろん架空のもの)です。まず、ここまでで、Admin-Consoleは接続できるようになりました。

fmsadmin stop adminserver -u admin -p password
fmsadmin start adminserver -u admin -p password
fmsadmin stop wpe -u admin -p password
fmsadmin start wpe -u admin -p password

しかし、まだ、Webサーバがこれでも動きません。次に行ったのは、次のようなコマンドです。

cd /Library/FileMaker\ Server/HTTPServer/
sudo touch stop
sudo touch start

つまり、FileMaker ServerのディレクトリにあるHTTPServerというディレクトリの中のstopおよびstartというファイルの更新日時を現在にします。別の記事で紹介した通り、このファイルが変更されると、FileMaker ServerのWebサーバが停止あるいは開始します。ここまでやると、実際にWebサーバが動き出しました。

fmsadminによるwpeサービスのstart/stopは不要なのかもしれませんが、Webサーバのデーモンhttpdを強制的に動かさないといけないのかもしれません。

FileMaker Server 13とOS X ServerのWeb

FileMaker Server 13と、OS X ServerのWebサービスの共存は基本的にはできません。となると、OS X ServerのWikiとかはあきらめるか、設定ファイルをあれこれということになりますが、ともかくいったんあきらめてFMS13を入れるといういう場合、80番と443番ポートが使われているのでインストールができないというメッセージに出くわします。

Webサービスを止めても、Wikiを止めてもまだそのメッセージが出ます。コマンドで落としてインストールしていたりしましたが、再起動したらやっぱりFMS側がだめになってどうしようもありません。徹底究明した結果、なんと、WebDAVが動いていました。ファイル共有でWebDAVを利用すると、Webサービスがオフでも、80番ポートを使ったhttpdが動いています。

では、WebDAVを全部オフにして再起動してみます。それでも、httpdは動いています。どうやら一度オンにすると、テコでも動くようです。そこで、すべての共有ポイントでWebDAVがオフになっていることを確認して、以下のコマンドを入れれば、おそらくすべてのプロセスが止まります。念のため再起動してもhttpdが動かないことも確認します。

sudo launchctl unload -w /System/Library/LaunchDaemons/org.apache.httpd.plist

httpdが動いているかどうかを確認するには、以下のコマンドを入れてください。このコマンドで80番や443番ポートをLISTENしているプロセスが見えるはずです。このコマンドで何も出てこなくなれば、OS X ServerのHTTPDのサービスはすべて止まった事になります。

sudo lsof -i | grep httpd

こうしてFMSをセットアップしますが、Web関連のフォルダが大きく変わります。/Library/FileMaker Server/HTTPServer以下に必要なファイルがあります。Webの公開フォルダはHTTPServer/htdocsにあります。ここにファイルを起きますが、httpdプロセスはfmserverアカウントで稼働していることに注意が必要です。_wwwではありません。

設定ファイルは、HTTPServer/conf/httpd.confがまず読み込まれます。設定を変更するには、まずこのファイルから確認しましょう。OS X Serverのよう「全部バーチャルホスト」的な設定ではなく、デフォルトのドキュメントエリアを使います。以下はその設定例です、ほとんど自分のメモみたいなもんです(笑)。赤字は追加記述です。.htaccess等を稼働させるには、AllowOverrideの指定が必要です。PHPはすでに動いていますが、既定のファイルはindex.htmlだけです。なので、DirectoryIndexの指定も行います。もちろん、必要に応じて設定は加えます。

<Directory "${HTTP_ROOT}/htdocs">
     Options All -Indexes -ExecCGI -Includes
     AllowOverride All
     Order allow,deny
     Allow from all
 </Directory>

DirectoryIndex index.php index.html

ここで、設定ファイルを変更したらapachectl gracefulと思いたいところですが、普通にこのコマンドを入れても、OS X ServerのApacheの状況を変えようとするだけで、FMSが起動しているhttpdには適用されません。FMSのhttpdのスタート、ストップ、そして設定の反映は、次のようなコマンドを打ち込みます。

sudo touch /Library/FileMaker\ Server/HTTPServer/start
sudo touch /Library/FileMaker\ Server/HTTPServer/stop
sudo touch /Library/FileMaker\ Server/HTTPServer/graceful

もちろん、フルパスでなくてもかまいません。これらのファイルの修正日を更新するのです。こうすると、/S/L/LaunchDaemonsにあるcom.filemaker.[start|stop|graceful].plistによるファイル修正の監視が行われていて、FMSのhttpdデーモンの処理を行います。これらのlaunchdファイルを見れば分かりますが、/Library/FileMaker Server/HTTPServer/bin/httpdctlというコマンドが用意されていて、このコマンドを経由して、httpdをコントロールするようです。

そういうわけで、設定ファイルを変えてはsudo touch gracefulとやればいいということです。日曜日はOS X ServerとFileMaker Serverのメンテで終わってしまった…。

FileMaker Server 13の管理コンソールが別のコンピュータから接続できない理由

*** 内容が少し違っていたので、修正しました。2013/20/50 ***

FileMaker Server 13になって、管理コンソールが純粋なWebアプリになり、クライアント側ではJavaのバージョンなどは気にしなくてもいいようになりました。これは非常に便利です。サーバ側はTomcatなので相変わらずJavaですが、そちらは管理された環境なので、利用者はJavaのバージョン等は気にしなくていいようになりました。

一方、FMS13では、16000ポートがHTTPSで、16001ポートがHTTPでの接続ができるようになっています。管理コンソールへの接続条件は、インストールしたサーバでは「https://localhost:16000」「http://localhost:16001」で接続ができます。FMS12のときと、HTTPSとHTTPが入れ替わっています。また、他のコンピュータから「https://ホスト名:16000」での接続は可能ですが、「http://ホスト名:16001」の接続はできません。

なぜか? パケットをキャプチャしてみました。コンソールへのログインをするときに、クライアントからサーバへのリクエストをダンプしてみました。以下の最初の数行の固まりはヘッダです(クッキーは省略しています)。そして、行をあけて1行だけあるのがボディです。

POST /admin-console/APP/connector/3/304/login HTTP/1.1
Host: homeserver.msyk.net:16001
Connection: keep-alive
Content-Length: 29
Cache-Control: max-age=0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8
Origin: http://homeserver.msyk.net:16001
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_9_1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/32.0.1700.77 Safari/537.36
Content-Type: application/x-www-form-urlencoded
Referer: http://homeserver.msyk.net:16001/admin-console/APP/connector/3/304/login
Accept-Encoding: gzip,deflate,sdch
Accept-Language: ja,en-US;q=0.8,en;q=0.6
Cookie: JSESSIONID=6706...888

username=admin&password=abcdef

わお!ユーザ名とパスワードがそのまま流れています(もちろんabcedfは置き換えてあり、abcdefの代わりに本物のパスワードが見えました)。ハッシュですらありません! つまり、localhostからの接続でないと、通信経路上での盗聴で簡単にログインのアカウントとパスワードを取り出せてしまうのです。サーバのコンピュータからしかログインできなくなっているのはそのためでしょう。同一コンピュータ内なら、パスワードをそのまま流しても、問題になることはないと言えます。しかし、他のコンピュータから接続するという状況では明らかに問題です。すなわち絶対に通信そのものを暗号化しないと危険なので、HTTPSでの接続しかできなくなっています。

それでも、どうしても、他のコンピュータから16001ポートを使って管理コンソールに接続したいという方は、以下のファイルを修正してください。OS Xでは必要に応じてsudoで作業をしましょう。Windowsは、多分、「FileMaker Server」がProgram Filesにあると思うので、それ以下は同じと思います。

/Library/FileMaker Server/Admin/admin-master-tomcat/conf/server.xml

このファイルの最初に以下の部分があります。開いて「16001」を検索します。このポート番号はここだけです。最後の方の下線、赤字の部分を削除してファイルを保存してください。

<Connector port="16001" protocol="HTTP/1.1" maxHttpHeaderSize="8192" maxThreads="150"
 minSpareThreads="5" maxSpareThreads="75" enableLookups="false"
 redirectPort="8443" acceptCount="100" connectionTimeout="20000"
 disableUploadTimeout="true" address="127.0.0.1" URIEncoding="UTF-8"/>

この後、サーバの再起動をしますが、管理コンソール自体を再起動させます。うまく行かない場合にはコンピュータの再起動を行いましょう。そうすれば「http://ホスト名:16001」で管理コンソールに接続できます。ホスト名はIPアドレスでももちろんかまいません。

くれぐれも、この状態で、インターネット経由での接続は細心の注意を払ってください。パスワードがバレない限りは他人にアクセスはできませんが、現状では容易にバレてしまうような通信方法です。安心な方法は、FMS13を稼働させているコンピュータにVPNで接続することですが、一手間増えるならVNCでサーバにログインしてページを開くのとあまり変わらないですよね。したがって、こうした変更はしないで、現状通り使うのが安全です。あるいは、自己署名証明書である点が微妙ですが、16000ポートで接続しましょう。いくら暗号化されているとは言え改善を期待したいですが、次のバージョン以降なのでしょうか。

FileMaker Server 13の「デーモングループ」とは何か?

FileMaker Server 13のインストーラで次の図のような画面が出てきます。FileMaker Server 12までは、fmserverという決められたユーザでしか稼働できなかったのですが、任意のユーザでの実行が可能になったのです。

shot0050

つまり、今ログインしているユーザで稼働させることができるのです。そうなると、FileMaker Server内のフォルダやファイルが、ログインしているユーザが所有者となるため、削除や名前の変更をアクセス権のことを気にしないでできるようになります。自分のMacにFileMaker Serverを入れて開発をしている人に取っては一手間、二手間が減るということになります。以下の図は、私のmsykのアカウントでインストールした結果です。Web用のファイルのフォルダやデータベースのフォルダの所有者がmsykとなり、ログインしている私msykに読み書き権限があります。

shot0052

このように、fmserverアカウント以外での運用をするには、インストーラでインストールするときに指定をします。しかしながら、ログインをしているユーザを単に指定すると次の図のようなシートの警告が出て来て、インストールができません。

shot0051

デーモングループ? なんでしょうか? これ、日本語にすると意味が分からないのですが、OS Xにはdaemonという名前のグループアカウントがあり、そのグループに所属しているユーザでないと、指定ができないですよということです。なので「daemonグループ」と翻訳しないで書かないと意味は通りません。既定値ではdaemonグループには、rootユーザしか登録されていませんが、ここでは私のアカウントmsykを登録しておく必要があります。しかしながら、マニュアルに具体的には書かれていません。システム環境設定ではできません。

では、どうすればいいでしょうか? 以下のように、ターミナルでコマンドをたたいてください。どうしてもGUIで作業したいという方は、「ワークグループマネージャ」をダウンロードしてやれなくはないですが、手順は簡単ではありませんので、ここでは省略します。コマンドの方がはるかに簡単です、と言い切ります。msykの箇所は実際に利用するユーザ名に変えますが、あとはこのままです。2行目は追加されている事を確認するためのコマンドです。

sudo dseditgroup -o edit -a msyk -t user daemon
sudo dseditgroup -o read daemon

2つ目のコマンドでは、daemonグループに関するさまざまな情報が表示されるので、その中で、グループに含まれるユーザを示すdsAttrTypeStandard:GroupMembership以降にユーザ名が追加されているかを確認します。インストールの途中でターミナルを立ち上げて作業してもOKでした。

こんなコマンドは見た事がない? そんな方は、こちらの書籍をお勧めします(さりげない宣伝)。アカウントについても詳しく書籍で紹介があります。

こうしてインストールすると、fmserverdなどのデーモンやWeb共有のhttpdといったプロセスは、全部msykアカウントで稼働します。セキュリティ上大丈夫なのかと気にする人もいらっしゃるかもしれませんが、FileMaker Serverに変なバグがなければ大丈夫です。Webで公開するものは気をつけた方がいいかもしれませんが、たぶん、自分で開発しているアプリを入れるのが普通なので、通常のWebとは違ってグローバルIPにさらされることはほぼないこともあり、問題になることはほとんどないと思います。もっとも、こういう仕事をしている人は「問題になる状況かどうか」を自分で判断できるものじゃないかとも言えますし、自分で回避できるだろうとも言えます。

「FileMaker® Server 13入門ガイド」のp43に次のような事が書かれています。他のページにはアカウントの事はあまりきちんと書かれていません。インストールのところでも、ここを見ろというリファレンスがあるだけです。

OS X: アカウントは OS X のローカルユーザアカウントであり、ローカルファイルへのアクセス(デーモングループのメンバーシップを含む)に関して fmserver アカウントと同一の権限を持っている必要があります。ディレクトリサービス(Active Directory または Open Directory など)に由来するアカウントは使用できません。リモートボリュームにデータベースまたはオブジェクトデータフォルダを追加して設定する場合、アカウントはこれらのリモートフォルダに対する完全なアクセス権を持っている必要があります。

例によって解釈しづらい文章です。ここで、fmserverアカウントのアクセス権をidコマンドで確認してみます。ここで、1(daemon)、および61(localaccounts)がポイントなのではないかと思います。Open Directoryのアカウントは、localaccountsグループには所属していません。ローカルに作ったアカウントだと、足りないのがdaemonグループへの所属だけなので、前記の方法でFileMaker Serverの実行アカウントとして利用できるようになります。

$ id fmserver
uid=502(fmserver) gid=499(fmsadmin) groups=499(fmsadmin),1(daemon),12(everyone),61(localaccounts),100(_lpoperator),402(com.apple.sharepoint.group.1),240(com.apple.access_loginwindow)

FileMaker Server 13はWebDirectなどいろいろ新しい機能が増えていますが、こういう地道なところでも変化がありますね。