とあるエンジニアの闇歴史帳

コピペで使える便利Wiki ※現在構築中です。

ユーザ用ツール


webp:vol55

差分

このページの2つのバージョン間の差分を表示します。

この比較画面にリンクする

webp:vol55 [2020/06/23 14:10] (現在)
行 1: 行 1:
 +====== Code.010 CGI(Perl)ファイル処理 その3:「ファイルロック:flock 前編」 ======
 +<html><pre style="font-family:monospace; font-size:10pt">
 +   Code.010                                                 2002年12月16日発行
 +■━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━■
 +                           【 Webプログラミング 】
  
 +                       〜 猫的プログラマーとその軌跡 〜
 +■━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━■
 +
 +              ▼毎週月曜日に配信しています。
 +              ▼等幅フォントでご覧いただくとキレイに見えます。
 +              ▼登録・解除はこちらから可能です。
 +                &lt; http://www.ichikoro.com/webp/ &gt;
 +                  ※ぜひお友達にもご紹介ください(^^)/
 +
 +※お詫び
 +  前回(Code.009)のメルマガに誤植がありました。
 +  詳しくは以下のページをご覧ください。
 +    http://www.ichikoro.com/webp/bbs/sylpheed.cgi?c=r&amp;n=12
 +
 +  今後このようなことが無い様に十分チェックを行い、
 +  配信いたします。大変、申し訳ございませんでした。
 +
 +  また情報をお寄せいただいた方々、ありがとうございます。
 +  この場を借りてお礼申し上げます。
 +
 +
 +━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
 + CGI(Perl)ファイル処理 その3:「ファイルロック:flock 前編」
 +──────────────────────────────────────
 +前回、アクセスログを記録するCGIを作成しました。
 +
 +しかしこのCGIには同時にアクセスされるとデータファイルが壊れてしまう
 +という欠点があったのです。そこで今回は「ファイルロック」を導入して
 +みようと思います。
 +
 +↓前回の内容はコチラ
 +http://www.ichikoro.com/webp/bk/00054/
 +
 +
 +    Mission : ファイルロックに対応したアクセスログを記録するCGIを作成せよ
 +    ‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾
 +        ○問題
 +            前回作成したCGIを、ファイルが壊れにくくなるよう改良せよ。
 +
 +
 +───────
 +    ソース
 +───────
 +#!/usr/bin/perl
 +
 +;#
 +;#ログ記録CGI ファイルロック対応版
 +;#
 +
 +#----------------------------------------------------------------------#
 +#                            モジュール                                #
 +#----------------------------------------------------------------------#
 +use strict;                #コーディングを厳格化
 +use Fcntl qw(:flock);      #定数 LOCK_* を取り込む
 +
 +#----------------------------------------------------------------------#
 +#                           グローバル変数                             #
 +#----------------------------------------------------------------------#
 +package G;
 +BEGIN{
 +    #■画像ファイル
 +    $G::IMG_FILE = "1pix.gif";
 +}
 +
 +
 +#======================================================================#
 +#                           メインルーチン                             #
 +#======================================================================#
 +package main;
 +{
 +    my $t = time();
 +    my $date = util::get_date($t);        #現在の日付取得(YYYY/MM/DD)
 +    my $time = util::get_time($t);        #現在の時間取得(hh:mm:ss)
 +    my $file;
 +    my $str;
 +
 +    #-----------------------------------#
 +    #            ファイル名作成         #
 +    #-----------------------------------#
 +    $file  =  $date;         # $file = YYYY/MM/DD
 +    $file  =~ s/\///g;       # $file = YYYYMMDD
 +    $file .=  ".dat";        # $file = YYYYMMDD.dat
 +
 +
 +    #-----------------------------------#
 +    #             文字列作成            #
 +    #-----------------------------------#
 +    $str = join("\t"
 +                        , $date                   # YYYY/MM/DD
 +                        , $time                   # hh:mm:ss
 +                        , $ENV{'HTTP_REFERER'   # このCGIを呼び出したページ
 +    );
 +
 +    $str .= "\n";    #最後に改行
 +
 +
 +    #-----------------------------------#
 +    #              書き込む             #
 +    #-----------------------------------#
 +    open(DAT, "&gt;&gt;$file") or die("Can not open file : $file ($!)");
 +    flock(DAT, LOCK_EX);            #ロック!
 +    print DAT $str;
 +    flock(DAT, LOCK_UN);            #ロック解除
 +                                    # closeすると自動的に解除されるため
 +                                    #  必要が無ければしなくても良い。
 +    close(DAT);
 +
 +
 +    #-----------------------------------#
 +    #              画像表示             #
 +    #-----------------------------------#
 +    $|=1;
 +    print "Content-type: image/gif\n\n";
 +    open(IMG, $G::IMG_FILE) or die("Can not open file : $file ($!)");
 +    binmode(IMG);               #バイナリだと指定(UNIXで使用する場合は必要ない)
 +    print while(&lt;IMG&gt;);
 +    close(IMG);
 +
 +
 +    #-----------------------------------#
 +    #              正常終了             #
 +    #-----------------------------------#
 +    exit(0);
 +}
 +
 +
 +package util;
 +
 +#--------------------------------------------------------------#
 +#■YYYY/MM/DDを返す
 +#    内容:指定された時間を、「YYYY/MM/DD」のフォーマットにした
 +#          文字列を返却する。
 +#
 +#    引数:(1)timeの戻り値:スカラー
 +#  戻り値:YYYY/MM/DD:スカラー
 +#--------------------------------------------------------------#
 +sub get_date{
 +    my $time = shift;
 +    my ( $yyyy, $mm, $dd ) = (localtime($time))[5,4,3];
 +
 +    $yyyy += 1900;
 +    $mm   += 1 ;
 +
 +    return( sprintf("%4d/%02d/%02d", $yyyy, $mm, $dd) );
 +}
 +
 +
 +#--------------------------------------------------------------#
 +#■hou:min:secを返す
 +#    内容:指定された時間を、「hh:mm:ss」のフォーマットにした
 +#          文字列を返却する。
 +#
 +#    引数:(1)timeの戻り値:スカラー
 +#  戻り値:hh:mm:ss:スカラー
 +#--------------------------------------------------------------#
 +sub get_time{
 +    my $time = shift;
 +    my ( $hou, $min, $sec ) = (localtime($time))[2,1,0];
 +
 +    return( sprintf("%02d:%02d:%02d", $hou, $min, $sec) );
 +}
 +
 +__END__
 +
 +
 +───────
 +   実行方法
 +───────
 +テキストエディタ(メモ帳やSimpleText)などで上記のソース(プログラム)を
 +保存してください。適当な名前(xxxx.cgi)でOKです。
 +    ※上記のソースは、Windows95,98,Meでは動作しません。
 +      NT,2000では動作します(XPは未確認)。
 +
 +CGIの詳しい実行方法については、Code.001をご参照ください。
 +http://www.ichikoro.com/webp/bk/00046/
 +
 +
 +───────
 +    解  説
 +───────
 +
 +○flock関数を使おう!
 +    排他制御(今回の場合、同時に書き込みが行われない制御)を最も
 +    簡単に実装する方法に、flock関数を使うという手法があります。
 +
 +    flockは、下記のように
 +
 +&gt;        use Fcntl qw(:flock);
 +&gt;
 +&gt;        open(DAT, "&gt;&gt;file.txt") or die("can not open file");
 +&gt;        flock(DAT, LOCK_EX);
 +
 +    ファイルを開いた後に、ロックしたい対象のファイルハンドルと、
 +    どの形式でロックするかを指定するだけでOKです。
 +
 +        flock([ファイルハンドル], [ロックモード]);
 +
 +
 +    ロックモードには下記のような物があります。
 +
 +        ・LOCK_SH(共有ロック)
 +            他プロセス(他に動いているCGIなど)が、既にこのモードで
 +            ロックしている場合、ロックが解除されるまで待つ。
 +
 +            解除され次第、他のプロセスからの書き込みをブロックする。
 +            読み込みはOK。
 +
 +        ・LOCK_EX(排他ロック)
 +            他プロセス(他に動いているCGIなど)が、既にこのモードで
 +            ロックしている場合、ロックが解除されるまで待つ。
 +
 +            解除され次第、他のプロセスからの書き込み・読み込みを
 +            ブロックする。
 +
 +        ・LOCK_NB(ブロックしない)
 +            他のモード(LOCK_SHなど)と同時に指定します。
 +            例えば
 +
 +                flock(DAT, (LOCK_SH|LOCK_NB))
 +
 +            とした場合、他のプロセスにより既にロックされている場合は、
 +            解除を待たずにすぐさま偽値を、成功すれば真を返します。
 +
 +        ・LOCK_UN(ロック解除)
 +            ロックを解除します
 +
 +
 +    ちなみにこれらのロックモードの情報はあらかじめ
 +
 +        use Fcntl qw(:flock);
 +
 +    とFcntlモジュールをあらかじめ呼んでおかないと、使用できません。
 +    もしFcntlが使用できない場合は、以下の数値を使用することで同様の
 +    処理が行えます。
 +
 +        LOCK_SH ..... 1  flock(DAT, 1);
 +        LOCK_EX ..... 2  flock(DAT, 2);
 +        LOCK_NB ..... 4  flock(DAT, 4);
 +        LOCK_UN ..... 8  flock(DAT, 8);
 +
 +    どうしても上記の文字列で指定したい場合、
 +
 +        #-------------------------#
 +        #       パターン1         #
 +        #-------------------------#
 +        sub LOCK_EX{
 +            return(2);
 +        }
 +
 +        flock(DAT, LOCK_EX);
 +
 +        #-------------------------#
 +        #       パターン2         #
 +        #-------------------------#
 +        use constant LOCK_EX =&gt; 1;
 +    
 +        flock(DAT, LOCK_EX);
 +
 +    といった形で代用が可能です。
 +
 +
 +
 +○ロックを解除したい場合は?
 +    簡単です。
 +    処理が終了したら、
 +
 +&gt;        flock(DAT, LOCK_UN);
 +
 +    と、同じようにファイルハンドルと「ロック解除」と指定する
 +    だけでOKです。
 +
 +    ただし、
 +
 +        open(DAT, "&gt;&gt;file.txt");
 +        flock(DAT, LOCK_EX);
 +        print DAT $string;
 +        close(DAT);
 +
 +    というように、そのままcloseした場合でも自動的に解除されるため、
 +    必要性がない場合はそのまま閉じても問題ありません。また、プログ
 +    ラムが途中で異常終了した場合も、自動的に解除されます。
 +
 +
 +───────
 +   次回予告
 +───────
 +こんなに便利なflockですが、いくつかの落とし穴があり、
 +使い方を誤まると、flockしていないのと同じくらい簡単に
 +壊れてしまうのです。
 +
 +次回はそんな事例をお目にかけましょう〜。
 +
 +
 +───────
 +   配信予定
 +───────
 +ファイル処理編の配信予定一覧です。
 +
 +    ・CGI(Perl)ファイル処理 その1:「ファイルを読む」
 +      http://www.ichikoro.com/webp/bk/00053/
 +    ・CGI(Perl)ファイル処理 その2:「ファイルへの書き込み」
 +      http://www.ichikoro.com/webp/bk/00054/
 +
 +    ・CGI(Perl)ファイル処理 その3:「ファイルロック:flock 前編」<<今回
 +    ・CGI(Perl)ファイル処理 その4:「ファイルロック:flock 後編」
 +    ・CGI(Perl)ファイル処理 その5:「ファイルロック:mkdir編」
 +    ・CGI(Perl)ファイル処理 その6:「ディレクトリ操作」
 +
 +
 +都合により追加・変更・中止になる可能性があります。
 +取り上げて欲しいテーマやご意見・ご要望はぜひ以下まで
 +およせください。
 +
 +    ・BBS
 +      http://www.ichikoro.com/webp/bbs/
 +
 +    ・メール
 +      mm-webp@ichikoro.com
 +
 +───────
 +  分からない
 +───────
 +いまいちよく分からない場合は、以下へれっつらごー。
 +
 +  ・サポートBBS
 +    このメルマガ専用のサポート掲示板です。
 +    疑問などがあったら、お気軽に書き込んでやってください(^^)/
 +      http://www.ichikoro.com/webp/bbs/
 +
 +  ・CGIプログラミングML
 +    CGIなどWebに関する話題を繰り広げるメーリングリスト。
 +    このメルマガとは関係ありませんので発言時は注意を。
 +      http://www.ichikoro.com/cgi/ml/
 +
 +
 +━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
 +                           編    集    後    記
 +━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
 +先週、我が家にもADSLがやってきました。
 +Yahoo!BBの契約数が150万人を突破するなど、飛ぶ鳥を落とす勢いの中、
 +私が選択したのは、値下げしてもやはり値段的に高いフレッツADSL。
 +
 +Y!ってINSネット64からの移行は受け付けてるんですが、INSネット64ライトは
 +断られるんですよね。サポートに問い合わせたら出来る言うてたのに!(怒)
 +    ※その後、Y!のお兄ちゃんに「サポートが何でそんなこと言ったのか
 +      分かりません」と言われる始末(ーー;) 頼むよ〜(泣)
 +
 +で、めんどくさくなって思わずNTTというわけです。
 +電話口に出た人に仕事柄色々と聞いていたのですが(^^;
 +埼玉県のADSL契約数のうち6割はY!だそうで、NTTが抜かれてしまったんですよ、
 +とポツリと言われました。最近やけにPRを頑張っているのはそのせいだったのか。
 +
 +
 +それはともかく最高です!
 +動画もスイスイですよ、奥さん。設定も難しくなく、30分程度あれば(慣れた人な
 +らもっと早い)あっと言う間に高速体験が可能です。
 +
 +そうそう、「フレッツスクウェア」というブロードバンドという状況を満喫できる
 +Webサイトがフレッツユーザー向けに提供されていたりします。一番最初に目にとま
 +ったのは赤坂泰彦さんが司会を務める「フレッツインタビュースクウェア」。
 +高校受験の時(と言っても推薦でしたが(^^;)、赤坂さんのミリオンナイツを聞いて
 +ころを思い出し、何だか懐かしい感じがして胸が熱くなりました。
 +
 +ちなみにゲストは新山千春、橋本真也、ベッキー、来月は藤咲奈々子と意外(?)
 +に豪華。無料ですので、興味のある方は一度ご覧くださいませ。
 +    ※しつこいようですがフレッツユーザーだけです(ニヤリ)
 +
 +    ・フレッツス・クウェア
 +     東日本 http://www.ntt-east.co.jp/flets/square/index.html
 +      西日本 http://www.ntt-west.co.jp/flets/office-s/index.html
 +          ※一部地域除く
 +
 +
 +また来週お会いしましょう (^-^)/~~
 +■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■
 +
 +                   【 Webプログラミング Code Sample 】
 +
 +                    発  行 : ichikoro.com
 +                発行責任者 : 勝部 麻季人
 +                              &lt; mailto:katsube@ichikoro.com &gt;
 +                 Webサイト : &lt; http://www.ichikoro.com/webp/ &gt;
 +            お問い合わせ先 : &lt; mailto:mm-webp@ichikoro.com &gt;
 +
 +                            Powerd by まぐまぐ
 +    All Right Reserved, CopyRight(C) 2001 Webプログラミング Code Sample
 +■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■
 +</pre></html>

関連ページ

webp/vol55.txt · 最終更新: 2020/06/23 14:10 (外部編集)