• ベストアンサー

ファイルロックの質問

プロバイダ:VC-NET スクリプト:Perl 在庫管理などで、在庫を変更中に変更前の値を第三者が閲覧してしまうと矛盾がおきますよね?そこで質問なのですがこの様な場合みなさんどうされてるのですか? 私は、書き換えるファイルを file → file986172208 アクセスした時間(Perlのtime)を付加してファイルロックをして、 書き込みを終えれば file986172208 → file また元に戻す。 イントラネット上では期待した結果が得られたのですが、いざアップしたら ”サーバー側のエラーですよ”と表示されました。 ですがTELNETから動作させるとうまく動作しました。 ファイルのパーミションは スクリプトファイル:755 データファイル:666 です。 みなさんからのご意見お待ちしています。

質問者が選んだベストアンサー

  • ベストアンサー
回答No.1

まず、イントラネット上で動作したというのは、どういうふうに実 行させたら動作したという意味でしょうか?それは、ローカルな WEBサーバー経由の cgi として動作したのか、telnet で動作させ たのと同レベルなのかですが。 あと、どういうエラーが起きたのかは、わからないのでしょうか? スクリプトの各段階で、どこまで進んだか、どういう状況かを、適 当なファイルにログとして残して行って、解析した方がいいと思い ます。そのファイルさえ作成されないのであれば、スクリプトの起 動もできてないのかもしれませんし。 それから、ロックの方法としては、ファイル名の rename で行って いるということですね?rename に失敗したら、ロック失敗という 方式でしょうか?原理的には正しくロックできる方法だと思います。 # もっとも、時刻を付加しなくても、共通のファイル名を使っても # 大丈夫なはずです。もしそれでだめだとすると、時刻を付加して # も1秒以内に複数のアクセスがあると破綻しますから。 ただ、何かの原因で更新中に file という名前のファイルが作成さ れないことと、更新中にそのスクリプトが死なないことが保証でき なければいけません。前者が起きると多重のアクセスが生じますし、 後者が起きるとデッドロックになります。 unix のサーバーで perl を使い、そのサーバー内のプロセス同士 でロックするのなら、flock を使うのが確実だと思います。 man perlfunc で flock の項目に使用例もあるので、見てください。

tarkey
質問者

補足

さっそくのご回答ありがとうございます m(_ _)m イントラネット上で動作したというのは、ローカルでWEBサーバーをたてて、 そこからCGI経由で動作したということです。 サーバー:httpd 1.27c(フリーウェア) それから初歩的なことなのですがエラーログは自分で取れるものなのですか? サーバー側が作ってくれるものだとばっかりおもってました。 だとしたらどのようにすればいいのでしょうか?(次から次へと質問が…) flockはファイルをオープンしたりライトする際に有効なんですよね? データをユーザーが入力してる間はずーーとロック状態でないとまずいんですよ。 ”いま100個あったのに発注かけたら0個だと!?どうなってるんだ”とか… ロック方法は、ファイル名の rename で行っています! 参考:http://www.din.or.jp/~ohzaki/perl.htm#File_Lock 今回が初めての投稿なので、何分的確に質問できていませんがもう少しお付き合いください。宜しくお願い致します。

すると、全ての回答が全文表示されます。

その他の回答 (3)

回答No.4

パーミッションについて: httpd の設定にもよりますが、~daresore にある cgi を実行した 場合には、daresore の権限にするのが普通ですから、本人が読み 書きできるなら cgi プログラムにもできると考えてもいいかと思 います。でないと、自分のディレクトリのファイルが他人の cgi プログラムからアクセスできることになります。もっとも、それが 確かかどうかは、ログをちゃんと調べる必要があります。 ログについて: 適当なログファイルを open(STDERR, ">/tmp/logfile"); のようにオープンして、自分で print STDERR ...; していけばいいだけのことです。ログを作るにもパーミッションの 問題がからむと面倒なので、/tmp か /var/tmp の使用が許されて いるなら、とりあえずはそこに作るのがいいでしょう。どういう権 限で動いているかは、そのログファイルのオーナーが自分かどうか で調べられます。 で、目的のファイルが rename に失敗したり、open できなかった ら、 die "$!"; か warn "$!"; しておきましょう。 ロックの方法について: 一般論として、長時間ロックをするのはよくありません。 「いま100個あったのに発注かけたら0個だと!?どうなってるんだ」 の問題は、顧客が発注するのが遅かったせいにすればいいのです。 でないと、100個あったことは確認したけど、発注せずにいきなり 接続を切ったりしてしまったらどうなりますか?cgi プロセスがそ のことに気付いて、ファイル名を戻すまでは、他の顧客は100個あ ることすら確認できなくなりますよ。

tarkey
質問者

お礼

返事が送れて申し訳ございません。 エラーログの作成うまくいきました!これからはこのようなエラーは ログから探っていきます。お忙しいところ本当にありがとうございました。 また今度はデッドロックしても定期的にチェックするプログラムなんかも作成したいですね。これからも何卒宜しくお願いします。^^

すると、全ての回答が全文表示されます。
  • cocky
  • ベストアンサー率57% (232/402)
回答No.3

ファイル名のrenameを行うには、当該ファイルのあるディレクトリに対して書き込みを許可するPermissionが立っていないといけません。 今回の場合、sub_dirのPermissionが701になっているということですが、この場合nobodyはsub_dirに対する書き込み許可が与えられていませんので、renameに失敗しInternal Server Errorが出ていると思われます。 従って、sub_dirのPermissionを777にすれば予定通りの動作をすると思いますが。

tarkey
質問者

お礼

ご回答ありがとうございます。m(_ _)m サーバーのエラーが英語なのでついついめをそらしていましたが正しく”Internal Server Error”でした。 ちょっとしたスクリプトを書くときにCGI&Perlのポケットリファレンスを 読むのですが、記述されてました!! ”ファイルシステムを超えてファイル名を変更しようとすると通常失敗に終わります(プラットフォームに依存)。” 以前イントラネットで使用したOSはwindowsだったので意識してませんでしたがそれを意味していたなんて…。パーミション属性に書き込み許可があるのは分かっていましたがディレクトリにも同じことが言えるなんてホント新発見です(私だけ?)rename もまた然り、名前を 書・き・換・え・る ですね! いやー、普段は過去ログをみてるだけでしたが投稿することでたった一日で解決するなんて。回答をしていただいたみなさんに感謝の気持ちでいっぱいです。

すると、全ての回答が全文表示されます。
  • kazuya-i
  • ベストアンサー率21% (7/32)
回答No.2

ディレクトリのパーミッションがおかしいのでは? 補足 通常 *普通*の環境であれば、CGIの実行は、ログインアカウントではなく nobadyなどの専用のユーザーで実行されます。 それではちゃんとしたロックはかけられないと思いますが それは質問じゃないんですよね?

tarkey
質問者

補足

またまた回答いただきありがとうございます。(^v^) ご指摘を受けたディレクトリのパーミッションなのですが public_html(ルートのディレクトリ):701    |    sub_dir(サブディレクトリ):701      |      file(変更したいファイル):666                        です。 windowsユーザーにはパーミションたる概念がまったくないので、 ピンとこないのです、はい。 ”ログインアカウントではなくnobadyなどの専用のユーザーで実行されます。 ” ”それではちゃんとしたロックはかけられない” う~ん、難しいですね。ブラウザからアクセスすることが”nobadyなどの専用のユーザー”でアクセスしているということですかね? 変更するファイルのパーミッションを 666 で権限を与えてるとおもうのですが? 勉強になるHPなどありましたらご紹介ください。たびたびお手数をお掛けしますが宜しくお願い致します。

すると、全ての回答が全文表示されます。

関連するQ&A