Home日記コラム書評HintsLinks自己紹介
 

フィンローダのあっぱれご意見番 第106回「とりあえず鍵をかける」

← 前のをみる | 「フィンローダのあっぱれご意見番」一覧 | 次のをみる →

一時期はフレッツ・ISDNも不安定で全くどうしようもなかったが、 今世紀に入ってからこちらの環境は随分状態がよくなったようだ。 しかし、世間はADSLが着実にユーザを増やしているようだし、 光ファイバーを使った高速通信サービスも、100Mbpsのものが家庭向けに始まるそうだし、 何となく、時代に取り残されているような気がしないでもない。

時代遅れといえば、実は今ごろi-modeの携帯電話をgetしたのである。 世の中、i-アプリとかいう時代になってきたのだが、 パケット通信サービスを使いたいということで、 まだ最新機種にはその機能がないため残念ながらi-アプリ対応の機種はパスすることに。 しかも、今まではDoPa対応のモデルを使っていたので、28800bps でパケット通信ができたが、 i-modeが使えてかつパケット通信可能なモデルは、実は9600bpsしか速度が出ないのである。 しかも、パケットあたりの料金は1.5倍になってしまう。 それしか料金プランがないのだからどうしようもない。 最近は大きな添付ファイルをメールに付ける人も結構いたりして、 これでは安心してメールを読むこともできないが、まあ緊急用には使えるだろうという感じか。

そういえば、i-modeは当然Webサイトを見る機能があるわけだから、 自宅のサーバにアクセスすることもできるはずだ。 実際に試してみた。 確かにアクセスはできる。 ところが、パスワードの入力が、猛烈に面倒なのだ。 個人用に使っているサーバーが誰からでもアクセスできると、 とてもマズいことになるので、 アクセスするときに認証するような設定にしてある。 ユーザを入力するのはよいとして、問題はパスワード入力のテキストボックスだ。 アルファベットを入力してもエコーバックは「*」だから実際にどんな文字が入ったかわからない。 例えば「html」と入力するためには、 4486555 とキーを押すのだが、 同じキーを何度も押すと凄く不安になるのである。

そういえば、あるオンライントレードサービスがi-mode対応なので使ってみたが、 ユーザ認証時のパスワードは数字だけで指定する仕組みになっていた。 数字だけだと危ないのでは、とか思ったが、 確かにこれは数字だけにしておかないと、入力するのが大変だ。 数字だけなら、1つの数字を指定するために押すキーは1回で済む。 桁数が十分多ければ、セキュリティ上は問題なさそうだから、まあいいか。

自宅のサーバにi-modeで接続して何が面白いかというと、 そう言われてみると何に使ったらいいのかよく分からない。 @niftyのログは自宅のサーバでオートパイロットで取得できるから、 それをダイジェストにしてi-modeで読めるようにすればどこからでも読めるぞ、とか思ったのだが、 現状のパケット料金では非現実的なのである。

§

最近、ニュース系のサイトとか見ていると、 ちょっとしたアンケートがあって、あなたはどっち系の質問が書かれていたりする。 こういう機能がプログラマーズフォーラムのページにもあると面白い、 と思ってアンケート機能を追加しようとした。 CGIで書けば簡単じゃん、とナメてかかっていたら、意外と厳しい戦いになった。

  

アンケートとかカウンタをCGIで作る場合に最も注意が必要なのは排他処理である。 要するに、結果を同時に書き込まれないように工夫するという話だ。 もっとも、殆ど誰も使わないようなアンケートなら、 現実的には排他処理を考えるだけ無駄かもしれないが。

 

※ 回答者がいるかどうかの方が心配なのだ。

perlでロックを実現するには、flock というシステム関数を使えばよい。 ActivePerl Help なら、perlfunc という所で flock という文字列で検索すれば、 メールボックスをロックする処理の例が出ている。 これは大雑把にいえば、次のような手順になるようだ。

(1)ファイルをオープンして、
(2)そのファイルハンドルに対してflockをかけて、
(3)必要な処理をして、
(4)flockを使ってロックを外す、

「ようだ」というのもこれまた大雑把な表現だが、 実は情けない話、よく理解していないのである。 どう分からないのか説明したい。

まず、ファイルをオープンして、次にflockでロックする。 この順序は分かる。 オープンできなければロックもできない、というか、しても意味がない。 オープンできたのにロックできない場合は? ファイルの内容には触らずに終了させれば問題は発生しないはず。 では、オープンに成功し、ロックもできたし、必要な処理もできたとしよう。 次にどうすればいい?

手順としては、オープン、ロック、処理、アンロック、クローズ、というのが構造的に美しいと思う。 ファイルを2個オープンする時、 A,Bの順にオープンしたら、B,Aの順にクローズすると何となく美しいのと同じだ。 List 1 のような感じである。 List 1 はあえて構造が分かりやすいようにインデントしてあるが、 通常はこの処理ではインデントを付けないことに注意してください。

---- List 1 ----

  open IN, $infile;
   open OUT, ">$outfile";
    # IN, OUT を使った処理
   close OUT;
  close IN;

---- List 1 end ----

これに対して、List 2 のような書き方は、 INの有効期間とOUTの有効期間が交錯しているので、何となく美しくないような気がする。

---- List 2 ----

  open IN, $infile;
  open OUT, ">$outfile";
    # IN, OUT を使った処理
  close IN;
  # (1)
  close OUT;

---- List 2 end ----

ただ、この順序に全く意味がないかというと、あまり現実的ではないかもしれないが、 理屈だけなら多少のこじつけは可能である。 例えば、$infile をオープンしている時間をできるだけ短くしたい場合。 ほんの僅かではあるが、 List 1 の方が、 $outfile をクローズするのに必要な時間だけ、 $infile をオープンしている時間を短縮することができる。 あるいは、$outfile に対して行う処理が時間がかかるものならば、 最後に $infile を読んだらすぐにクローズしてしまえば、 その後時間のかかる処理をしてから $outfile をクローズするまでの時間が短縮できる可能性はある。

§

  

さて、 オープン、ロック、処理、クローズ、アンロック、という順序は、多分、原理的におかしい。 というか、ファイルがクローズされた時点でロックは解除されていると思われるので、 多分アンロック出来ないのではないか? だから、もしアンロックするのなら、順序としては オープン、ロック、処理、アンロック、クローズの順でなければならない。

 

※ perl では、ファイルを close したときにロックが解除されることになっている。

では一体何が気になるのか? アンロックしてからクローズするまでの僅かな間である。 これも非現実的かもしれないが、 アンロックしたその次の瞬間に、 何か他のプロセスがロックしに来るかもしれない。 ロックに成功したら、その次には同じファイルをオープンして上書きする可能性もある。 これではロックした意味がない。

というわけで、実は現在使っているCGIスクリプトは、 オープン、ロック、処理、クローズという順に処理している。 list.3 は実際のコードである。 見ての通り、アンロックの処理はコメントアウトしてある。 つまり、アンロックしていないのだ。 サンプルにないことすると、どうも精神的には落ち着かない。 果たして本当にいいのだろうか?

---- list.3 ----

######## ロック処理を行いつつ必要なファイルをオープンする
# $data は既存でなければならない
&error_exit("cannot open $data") unless (open IO, "+< $data");
&error_exit("cannot lock $data") if (flock(IO, $LOCK_EX) == FALSE);
&error_exit("cannot open $log\n") unless (open LOG, ">>$log");
&error_exit("cannot lock $log\n") if (flock(LOG, $LOCK_EX) == FALSE);

print LOG "$sys_date\n";

######## メインの処理
&body;

######## 後始末をする
# flock IO, $LOCK_UN;
close IO;
# flock LOG, $LOCK_UN;
close LOG;

---- list.3 end ----

§

  

こうやってとりあえずCGIは完成した。 というか未完成ですが、とにかく動くコードにはなっている。 そこで、これをRIMNETに転送して処理させようとした。 ところが、ここに大きな落とし穴があったのだ。 RIMNETではflockは正しく動作しないというのである。

 

※ 多分 NFS のせいだ。

公式アナウンスによれば、

「perl の flock 関数など、 OSが提供する ファイルのlock機能は、 複数のサーバーが並列動作をしておりますリムネットのWWWサーバーでは正しく動作しません。 」

というのだ。 これは困ったわけだが、 そういえば他の人も困っていると思うわけで、 一体RIMNETではロック処理をCGIで書く場合にどうやって実現しているのだろうか?

そういえば、CGIを作るには、確実に動作状況を把握できるサーバがあると便利である。 エラーが発生したときに、httpサーバのエラーログを確認すれば、 原因がはっきりすることがよくあるからだ。 ただ、レンタルサーバーなら別として、CGIが使えるプロバイダでも httpd の エラーログまで公開してくれるプロバイダは少ない(というか、あるのか?)ようだ。

そこで目をつけたのが、自宅で稼動しているapacheサーバだ。 これなら、全ての情報をチェックできる。 というか、もしかして、これで動作したものをそのまま公開すれば、ロックの問題は解決するのでは? どうせフレッツ・ISDNで24時間接続しているのだから、 外からアクセスできないこともない。 という経緯があって、現在は自宅のサーバの機能の一部を公開して使っている。 あまりトラフィックが多くなっては使い物にならないと思われるが、 アンケートのためのCGI処理に絞っているので、 これならどうせ1日の利用者は多くて数名程度なので、全く問題にならない。

というか、考えてみれば、 そんなに利用者が少ないのなら、わざわざロックしなくていいような気がするのだが…。

  

(C MAGAZINE 2001年4月号掲載)
内容は雑誌に掲載されたものと異なることがあります。

修正情報:
2006-03-11 裏ページに転載。

(C) Phinloda 2001-2006, All rights reserved.