• ベストアンサー

ファイルロックの質問

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

  • CGI
  • 回答数4
  • ありがとう数3

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

  • ベストアンサー
回答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

  • ロック??

    データファイルとかは同時書き込みされると破損するみたいですね。 それを防ぐにはとうすりゃいんだ?と思い書籍(十日でおぼえるPerl講座)をみるとFlock関数を使えばいいとありました。 しかし自分が使っているスクリプトのロック関数は MkdirとSymlinkだけです。 これはどうすればいいんでしょうか?

  • Perlでロック不具合?

    Perlを使用して、掲示板のようなものをつくり、ずっと稼動させていましたが、 今日、データが消えてしまいました。 データのファイルサイズがゼロになっていました。 ファイルの書込み時には、flockを使用してロックをかけています。 #--ロック flock LOCK,2; #--アンロック flock LOCK,8; どのような原因が考えられますでしょうか? flockが使用できることは、別途スクリプトを作って確認済みです。 環境 SuSE linux 9 Perl v5.8.3 書込みが最大で1日に30件程度 宜しくお願いします。

    • ベストアンサー
    • Perl
  • cgi(perl使用)でファイルを作る方法を教えてください

    こんにちは、 perlをやっています。 プロバイダ上にperlスクリプトを拡張子cgiでUPしています。 いまやりたいことがあるんです、それは ファイルをサーバ上の領域に作るというものです (ちなみにサーバの種類はUNIX系です) ファイルはゼロバイトの何も無いテキストファイルを作りたいんですが どのような関数を使えばファイルができるのでしょうか。 また、ファイルを作った後パーミッションの変更(chmodコマンドのような 動き)をする関数等があれば教えてください。

    • ベストアンサー
    • Perl
  • 携帯電話でCGIのファイルを読むと文字が・・・

    携帯電話で読めるようなホームページを作っています。 ところが、FORMでCGIファイルを見に行くと、日本語が文字が化けます。 CGIファイルはPERLですが、UNIXサーバでPERLスクリプトをSHIFT JISで書くとうまく動作しないことがある、と、手持の本には書いてありました。 みなさんは、どの様にされておられるのでしょうか? あるいは先の本に書かれていることは昔の話しで、今はUNIXのPERLでもSHIFT JISとCR+LFでスクリプトを書いても問題ないのでしょうか? よろしくお願いします。

    • 締切済み
    • CGI
  • 500 Internal Server Err で困ってます

    私、CGI初心者なんですが、”500 Internal Server Err ”が出てしまい困ってます。 カウンターの設置し、きちんと動いているんですが、フォームを入力してもらい、ファイルに保存するCGI(Perl)です。このエラーはスクリプトにエラーがある時や、FTPで バイナリモードでスクリプトを送ってしまった時などに起こると本に書いてありました。なので、次の事を試してみたんですが・・・ ・TELNETでPERLの構文チェックと動作確認 ・FTPでアスキーで再度アップロード ・再度スクリプトを検証 ・念のため、ファイルの属性をチェック ・念のため、.htaccessをチェック(改行コードなど、・・でもカウンタプログラムが動いているから問題ないはずですよね??) 以上の事を試したんですがダメでした。 そこで、もっと簡単なスクリプト(簡単な標準出力だけを するもの)を動かしてみたんですが、やはりダメで、上記のチェックをやってみたんですが、ダメでした。 この簡単なスクリプトはCGIの本で一番最初に載っている ものでわずか10行のものです。 TELNETで動作も確認したんですが・・・ 何分、初心者なもので・・・考えられることがあったら 教えていただけると助かります。

    • ベストアンサー
    • CGI
  • #!/usr/local/bin/perlの変更。

    ┬ cgi_script │   └***.cgi │ └ access_g     └11111       └22222         └***.cgi 今まで、cgi_scriptフォルダの直下にあるcgiファイルの一番上の行は #!/usr/local/bin/perl できちんと動作していました。 今は、そのcgi_scriptフォルダと同じところにあるaccess_gフォルダの中にある、 11111フォルダの下の2222フォルダの下にあるcgiファイルを実行させたいのですが、 #!/usr/local/bin/perl をどのように変更していいかわからなくなってしまいました。 動作させたいcgiファイルはcgi_scriptフォルダの中に入れたところきちんと動作したので、 動作上の問題はないと思われます。 どうぞよろしくお願いいたします。

    • ベストアンサー
    • CGI
  • perl初心者です。iモードのファイルサイズについて教えてください。

    perlをはじめて2週間ほどです。 素朴な疑問で申し訳ありませんが、perlであるファイルからデータを読み込み加工してHTMLで書出し、一部をあるファイルに書きこむスクリプトを作りました。 今パソコンで動作を確認しているところですが、いずれこれをiモードでも表示させたいと思っています。 だいたい何をすれば良いか掴めているつもりですが、素人が作ったスクリプトなのでファイルサイズが非常に問題になっています。 これをiモードで表示する場合のファイルサイズは、cgiのファイルサイズ+読み書きするファイルのサイズと解釈するのが妥当なのでしょうか。 教えてください。

    • ベストアンサー
    • CGI
  • PERL 宣言文 -wについて

    Perl初心者のWEBサーバエンジニアです。 サーバの移行に伴ってCGIファイルが動作していないため、ご相談になります。 【サーバ環境】 perl実行パス      /usr/local/bin/perl シンボリックリンク   /usr/bin/perl => /usr/local/bin/perl ソース記述       #!/usr/bin/perl ヴァージョン      5.8.5 perl実行環境      http://△△△.jp/cgi-bin/ ※apacheのスクリプトエイリアス指定 options +ExecCGI -Include SetHandler cgi-script 上記の環境で、cgiファイルが500internalサーバエラーになる現象が発生しています。 ファイルは以前動作したサーバから引っ張ってきました。 原因を探っていたのですが、cgiファイルのソース記述を #!/usr/bin/perl -w と記述を変更すると正常に動作しました。 -w について 【1度しか出現しない識別子や、初期化されずに参照される変数など、危険、無駄と思われる処理の警告を出力します。実際にはもっとたくさんの種類のチェックをするようです。】 と言う事はわかりましたが、いままで、-wなしで動作していたので、-wなしで動くよう、perlの設定を変更したいとかんがえております。 なにぶんPERL初心者ですので、同様の事象で知見がある方、ご教授を宜しくお願いいたします。

    • ベストアンサー
    • CGI
  • パスワードを外部ファイルから読み込む

    下記のようにcisco機器にloginして、show clockコマンドを事項するperlを複数の機器を対象に実行したいと現在考えております。 ログインパスワードにつきましては定期的に変更するよう運用しているため、外部のファイルを参照するように出来ればと思いますが、perl初心者のため方法が全く分かりません。ご教授頂ければ幸いです。 ****************** use Net::Telnet::Cisco; my $session = Net::Telnet::Cisco->new(Host => 'IPアドレス'); $session->login('login', 'ログインパスワード'); ←※ここを外部ファイルを参照するようにできればと考えています。 # Execute a command my @output = $session->cmd('show clock'); open(OUT,">showclock.txt"); print OUT @output; close(OUT); $session->close; ****************** よろしくお願い致します。

    • ベストアンサー
    • Perl
  • ASPでMDBファイルを更新する時のロックについて

    こんばんは ASP(VBスクリプト)で MDBファイル(アクセス2000)の データベースを 更新 又は レコード追加 をさせるときの ロックについて悩んでいます。 まず条件として このMDBファイルは 複数のユーザーが共有する物です。 (ここでは仮に A B C と3つのユーザーとします) データの新規登録の時(レコードの追加)はレコード内の項目で 絶対重複しないIDを発行して登録します。 逆に更新の時は そのIDを基に該当レコードを更新します。 また、IDはA*** B*** C*** と言うように 各ユーザーの固有ID+重複しない番号 と言う内容にしています 二重書き込み防止のために色々考えているのですが このIDを基にした方法だと 基本的にはAというユーザーが 同じIDの情報を複数のブラウザ開かない限り二重書き込みには ならないと思っています。 (変更登録などはパスワードで管理して物理的に1人(1画面)しかできないようにしています) なので物理的な2重書き込みはこれで防止できると思っているのですが 正しいでしょうか? ただ、ものすごく悩んでいるのが 1人が1つのデータベースをさわっているのなら良いのですが 複数人が同時に使っている場合、レコードが服従することはないので 2重書き込みはないとしても Aのデータを更新しているときに Bが新しく情報を追加したと言うような 事は起こるはずなので、ファイルが壊れないかと心配しています。 なので cgiで言うような書き込みロックのような事が ASPでもできるのかなと思っています。 ただ、それ以前に こういった使い方はダメでしょうか? (1つを複数人で使うこと) 良くない場合は A、B、C それぞれデータベースを作り それを結合させた方が賢明なのかなとも思っています。 ロックの方法でやるか 個々に作って結合させるか それ以外にもよい方法があるのか これで悩んでします。 また、ロックの場合 Updateではなく Recordsetオブジェクトを使って IDがあれば更新 なければ 追加 と言う方法にしようと 思っていまして その場合 OPENメソッド recordset.Open Source, ActiveConnection, CursorType, LockType, Options で、ロックタイプを3にしても これはUpdateの時だけ有効のようなので 意味がないのかなと思っています ただ MSのHPでの解説で >>レコード単位の共有的ロックを示します。Update メソッドを呼び出した場合にのみ、プロバイダは共有的ロックを使ってレコードをロックします。 と書いているのですが、そもそも >>共有的ロックを使ってレコードをロック と言う意味が分かっていません ファイルを壊さないためにも有効であるなら Updateを使う方法に変えようかとも思うのですが、どうなんでしょうか? なんか 基礎的なことが分かっていないので 分かりにくい質問になりましたが ファイルが壊れないような処理方法を作っていきたいので、ご教授のほど よろしくお願いします。