Code.010 2002年12月16日発行 ■━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━■ 【 Webプログラミング 】 〜 猫的プログラマーとその軌跡 〜 ■━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━■ ▼毎週月曜日に配信しています。 ▼等幅フォントでご覧いただくとキレイに見えます。 ▼登録・解除はこちらから可能です。 < http://www.ichikoro.com/webp/ > ※ぜひお友達にもご紹介ください(^^)/ ※お詫び 前回(Code.009)のメルマガに誤植がありました。 詳しくは以下のページをご覧ください。 http://www.ichikoro.com/webp/bbs/sylpheed.cgi?c=r&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, ">>$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(<IMG>); 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は、下記のように > use Fcntl qw(:flock); > > open(DAT, ">>file.txt") or die("can not open file"); > 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 => 1; flock(DAT, LOCK_EX); といった形で代用が可能です。 ○ロックを解除したい場合は? 簡単です。 処理が終了したら、 > flock(DAT, LOCK_UN); と、同じようにファイルハンドルと「ロック解除」と指定する だけでOKです。 ただし、 open(DAT, ">>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 発行責任者 : 勝部 麻季人 < katsube@ichikoro.com > Webサイト : < http://www.ichikoro.com/webp/ > お問い合わせ先 : < mm-webp@ichikoro.com > Powerd by まぐまぐ All Right Reserved, CopyRight(C) 2001 Webプログラミング Code Sample ■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■