CGIの質問です。メールアドレス保有数を日毎、月毎に表示するCGIを作りたいと考えています。list.datにはメールアドレスが以下のように並んでいます。

aaa@bbb.ccc,,,,,,
bb@dd.ee,,,,,,
eeee@ccc.fff,,,,,,
list.datの行数が現在のメールアドレス保有数です。
毎日CRONで23:59にCGIを起動し、その日のlist.datの行数を数えて記録します。
ブラウザで確認できるよう記録したデータは次のように表示します。

◆月毎
日付    増減数  アドレス保有数
2007/4    100   3280
2007/3    -20   3180
2007/2    300   3200

◆日毎
日付    増減数  アドレス保有数
2007/2/22   -5   3000
2007/2/21   20   3005
2007/2/20   30   2985

CGIの知識が設置できるくらいしか持ち合わせていないため、完全な回答をしていただいた方にはお礼として1000ポイントを差し上げます。どうぞよろしくお願いいたします。

回答の条件
  • 1人2回まで
  • 登録:2008/02/21 03:59:38
  • 終了:2008/02/23 04:12:00

ベストアンサー

id:kiryuu No.2

kiryuu回答回数16ベストアンサー獲得回数42008/02/21 22:14:31

ポイント1000pt

多次元連想配列もモジュールも使わずに作ってみました。

CRON呼びだし用(setlog.pl)と、表示用CGI(showlog.cgi)に分かれます。

ログファイルは、ログファイルのあるディレクトリのパーミッションを707にするか、予め空ログファイルを作成しておいてパーミッションを606にしておいてください。

CRON呼びだし用(setlog.pl)

#!/usr/bin/perl

use strict;

#ログファイルをサーバ内の絶対パスで記入
#もちろんそれぞれの環境にあわせる
my $logfile = '/home/kiryuu/www/test/2008.dat';	

#リストファイルをサーバ内の絶対パスで記入
#もちろんそれぞれの環境にあわせる
# データの構成は、日付,総数,前日との差
my $datfile = '/home/kiryuu/www/test/list.dat';

#リストファイルを読み込む
open(IN,$datfile);
my @list = <IN>;
close(IN);
# @listにはアドレスファイルの中身が1行ごとに入っている

#ログファイルを読み込む
my @log;
if(-e $logfile){
	open(LOG,$logfile);
	@log = <LOG>;
	close(LOG);
}

# @logを分解
my(%dat,%all,%diff) =();
foreach(@log){
	my($t1,$t2,$t3) = split("\,",$_);
	$dat{$t1} = $t1;
	$all{$t1} = $t2;
	$diff{$t1} = $t3;
	}
# %datには日付、%allには総数、%diffには前日との差が入っている
# %datはなくてもよいが、後々何かに使えるかもしれない
# ハッシュのキーは日付

# 日付をソートする
my @sdays = sort({$a <=> $b} keys(%all));
# @sdaysには日付が昇順に入っている

# 今日の日付を取得する
$ENV{'TZ'} = 'JST-9';
my ($mday, $mon, $year) = ( localtime(time) )[3..5];
my $today = sprintf( "%04d/%02d/%02d" , $year + 1900, $mon + 1, $mday);
# 今日の日付がYYYY/MM/DDの書式で$todayに入っている

# リストの総数を取得する
my $all_day = scalar(@list);
# $all{今日の日付}に@listの数が入る。
# = @list や = $#list+1 でも可

# 前日との差を取得する
my $diff_day = $all_day - $all{$sdays[$#sdays]};
# $sdays[$#sdays]は@sdaysの最後の日付。
# %allには総数が格納されているので、
# $all{最後の日付}には最終日の総数が入る。
# これを、今日の総数から引くと差が出る。
#
# なぜ差も記録するか=>
#	何らかの事情でログファイルを編集して古いデータを削除しても
#	先頭の日付で前日との差を表示させるため

# 書き込むデータを作成
my $wdat = join(',',$today,$all_day,$diff_day) . "\n";

# ログファイルを追記モードで開く。ついでに書く
open(LOG,">>$logfile");
print LOG $wdat;
close(LOG);
chmod 0666,$logfile;

# 終了する
exit();

表示用CGI(showlog.cgi)

#!/usr/bin/perl

#ログファイル
#こっちは相対パスでも大丈夫
my $logfile = './2008.dat';

# ハッシュ変数を定義
my(%day,%all,%diff) = ();

# ログファイルを読み込んでハッシュに格納
open(LOG,$logfile);
my $tmp;	#使い捨ての変数
while($tmp = <LOG>){
	#改行文字を取り除く
	chomp $tmp;
	#使い捨て変数にログの内容を分割して格納
	my($t1,$t2,$t3)=split("\,",$tmp);
	# $t1(日付)をキーにハッシュ変数に代入
	$day{$t1} = $t1;
	$all{$t1} = $t2;
	$diff{$t1} = $t3;
	}
close(LOG);
# %day,%all,%diffにそれぞれ値が入った




#日ごとの部分のHTMLソース作成
#ハッシュを日付順にソートして、前日との差分を計算する
my @sdays = sort({$a cmp $b} keys(%all));
#日付で回す。$_には日付が入る
my @src_day = ();	#HTMLソースの種リスト
foreach(0 .. $#sdays){
	#前日との差を取得する
	#はじめのデータの場合は%diffを用い、それ以外の場合は前日のデータとの差を用いる
	my $diff_t;
	if($_ == 0){
		$diff_t = $diff{$sdays[$_]};
		}else{
		$diff_t = $all{$sdays[$_]} - $all{$sdays[$_ - 1]};
		}
	push(@src_day,"<tr><td align=\"right\">$sdays[$_]</td><td align=\"right\">$diff_t</td><td align=\"right\">$all{$sdays[$_]}</td>\n");
	}

#日付部分のHTMLソースを完成させる
my $html_day = <<'_HTML_';
<table border>
<tr>
<th>日付</th>
<th>増減数</th>
<th>保有数</th>
</tr>
_HTML_
#リストを逆順(新しい方が上)にしてからソースに追加
foreach(reverse(@src_day)){
	$html_day .= $_;
	}
#テーブルタグを閉じます
$html_day .= '</table>';


#月のデータのソース作成
# @sdaysは使い回す
# %day,%all,%diffも使い回す
# 考え方:前月の最終日の総数-今月の最終日の総数=差

#月のハッシュを作成
my %m_hash = ();
foreach(@sdays){
	$_ =~ /^(\d{4}\/\d{2})\//;
	$m_hash{$1} = $1;	#重複分は上書きされる
	}

my %m_all = ();

#それぞれの月の最終日を取り出す
#まず、月に合致する日付を取り出す
foreach(keys %m_hash){
	my $month = $_;
	my @tmp;
	foreach(@sdays){
		if($_ =~ /^$month/){
			push(@tmp,$_);
			}
		}
	# @sdaysは以前にソートされているので、
	# @tempの最後の値がその月の最終日
	$m_all{$month} = $all{$tmp[$#tmp]};
	}
# これで、%m_allには、それぞれの月の最終日の総数が入った

# 月をソートする
my @smonth = sort({$a cmp $b} keys(%m_all));
# @smonthには、月が昇順で入っています。

# 前月との差を求めつつソースも作る。
# 但し、最初の場合は「--」とする。
my @src_month = ();
foreach(0 .. $#smonth){
	my $m_diff_t;
	if($_ == 0){
		$m_diff_t = '--';
		}else{
		$m_diff_t = $m_all{$smonth[$_]} - $m_all{$smonth[$_ - 1]};
		}
	push(@src_month,"<tr><td align=\"right\">$smonth[$_]</td><td align=\"right\">$m_diff_t</td><td align=\"right\">$m_all{$smonth[$_]}</td>\n");
	}

#月部分のHTMLソースを完成させる
my $html_month = <<'_HTML_';
<table border>
<tr>
<th>日付</th>
<th>増減数</th>
<th>保有数</th>
</tr>
_HTML_
#リストを逆順(新しい方が上)にしてからソースに追加
foreach(reverse(@src_month)){
	$html_month .= $_;
	}
#テーブルタグを閉じます
$html_month .= '</table>';



## HTMLにはき出します
$html_src = <<"_HTML_";
Content-type: text/html; charset=Shift_JIS

<html>
<body>
<h2>なんかタイトルとか</h2>
<hr>
◆月毎
$html_month
<hr>
◆日毎
$html_day
<hr>
</body>
</html>
_HTML_

print $html_src;

exit();

サブルーチンも使わず、上から下までダ~っと処理しているんで、長くなってすいません。

Templateモジュールが使えるなら、tkyk3さんの回答の方がスッキリします。

id:icta

早々の回答ありがとうございます。

早速、試してみたところ昨日23時59分にアドレス保有数を取得することができました。

本日同時刻に増減数を取得でき、希望通りの動作を確認しましたら改めてご報告いたします。

2008/02/22 03:43:36

その他の回答(1件)

id:tkyk3 No.1

tkyk3回答回数59ベストアンサー獲得回数62008/02/21 16:40:34

ポイント1000pt

ちょっと適当になってしまいましたが、作ってみました。

#!/usr/bin/perl

use strict;
use warnings;
use Template;
use CGI;
my $q = new CGI;#CGIとして実行した場合
#use Data::Dumper;

print $q->header( 	'-Content-Type'	=> 'text/html',
					'-charset' 		=> 'UTF-8',
				);

my $tt = Template->new();

my $address_filename  = 'list.dat'; #読み込むメールアドレスリスト
my $log_filename      = 'log.dat'; #ログを記録するファイル名
my $template_filename = 'template.tt'; #テンプレートファイル名
my $html_filename     = 'logview.html'; #ログHTMLファイル名

#アドレスファイルを読み込む
open(IN,"$address_filename");
my @data = <IN>;
close(IN);

#今日の日付を取得
$ENV{'TZ'} = "JST-9";
my ($mday, $mon, $year) = ( localtime(time) )[3..5];
my $today = sprintf( "%04d/%02d/%02d" , $year + 1900, $mon + 1, $mday); #今日の日付

my $list_num = @data; #リスト数
my $log_data = join( ',' , $today, $list_num ); #書き込むデータを生成

#ログファイルを読み込む
open(IN,"$log_filename");
my @log_datas = <IN>;
close(IN);

push(@log_datas, $log_data); #今日の状況を追加する
my @daily_logs;
my @monthly_logs;

foreach (0 .. $#log_datas) {
	($daily_logs[$_]->{date}, $daily_logs[$_]->{num}) = split(/,/, $log_datas[$_]);
}


my ($month_diff, $month);
foreach (0 .. $#log_datas) {
	$month = $daily_logs[$_]->{date};
	$month =~ s/\/\d{2}$//;
	if ( $month ne $month_diff && $_ > 0 ) { #月が変わったら
		push(@monthly_logs, { date => $month_diff, num => $daily_logs[$_ - 1]->{num} } );
 	}
 	elsif ($_ == $#log_datas) { #現時点で最後の日付
		push(@monthly_logs, { date => $month, num => $daily_logs[$_]->{num} } );
 	}
	$month_diff = $month;
}

#ログファイルに追記保存
open OUT,">>$log_filename";
print OUT "$log_data\n";
close OUT;

balance(\@daily_logs);
balance(\@monthly_logs);
@daily_logs   = reverse( @daily_logs ); #日付の新しい順にする
@monthly_logs   = reverse( @monthly_logs ); #日付の新しい順にする

#テンプレートをもとにHTML保存
$tt->process("$template_filename", { 
				daily => \@daily_logs ,
				monthly => \@monthly_logs ,
			 },
			 $html_filename
			 ) or die $tt->error();

#print "<pre>".Dumper(\@monthly_logs)."</pre>";
#print "<pre>".Dumper(\@daily_logs)."</pre>";

#--------------------------------------------------------------
#増減を追記
sub balance {
	my $log_ref = shift;
	my @output = @{ $log_ref };
	
	foreach (0 .. $#output) {
		if ( $_ > 0 ) { #2日目以降は増減を計算
			my $yesterday_num = $output[ $_ - 1 ]->{num};
			my $today_num	  = $output[ $_     ]->{num};
			$output[ $_ ]->{balance} = $today_num - $yesterday_num;
		}
		else { #最初は純増
			$output[ $_ ]->{balance} = $output[ $_ ]->{num};
		}
	}
}

上をlog.cgiとでもします。

my $address_filename  = 'list.dat'; #読み込むメールアドレスリスト
my $log_filename      = 'log.dat'; #ログを記録するファイル名
my $template_filename = 'template.tt'; #テンプレートファイル名
my $html_filename     = 'logview.html'; #ログHTMLファイル名

ここを書き換えると出力先などを変更できます。

例ですと、log.datに日ごとの数値が記録されます。

logview.htmlにHTML形式でログを出力します。

あと、テンプレート(ひな形)ファイルとして、

<html>
<head>
<meta http-equiv="Content-Type" content="text/html;">
<title>ログ集計</title>
</head>
<body>

<h2>◆月毎</h2>
<table>
<tr>
<th>日付</th>
<th>増減数</th>
<th>保有数</th>
</tr>

[% FOREACH m IN monthly %]
<tr>
<td>[% m.date %]</td>
<td>[% m.balance %]</td>
<td>[% m.num %]</td>
</tr>
[% END %]
</table>

<h2>◆日毎</h2>
<table>
<tr>
<th>日付</th>
<th>増減数</th>
<th>保有数</th>
</tr>
[% FOREACH d IN daily %]
<tr>
<td>[% d.date %]</td>
<td>[% d.balance %]</td>
<td>[% d.num %]</td>
</tr>
[% END %]
</table>

</body>
</html>

を、template.ttなどとして保存して同じディレクトリ内において下さい。ここの書式をもとに出力します。

id:icta

早々の回答ありがとうございます。

教えていただいた内容で試してみましたが、どうもうまく行きません。

log.cgiを実行するとInternal Server Errorが表示されます。

Template-Toolkitはsakuraの場合、インストールする必要があるようです。

現在以下のkiryuuさんよりいただいた回答で動作を確認中です。

明日、増減数を希望通りに取得できましたら質問を終了したいと思います。

明日改めてご報告いたします。

2008/02/22 03:48:49
id:kiryuu No.2

kiryuu回答回数16ベストアンサー獲得回数42008/02/21 22:14:31ここでベストアンサー

ポイント1000pt

多次元連想配列もモジュールも使わずに作ってみました。

CRON呼びだし用(setlog.pl)と、表示用CGI(showlog.cgi)に分かれます。

ログファイルは、ログファイルのあるディレクトリのパーミッションを707にするか、予め空ログファイルを作成しておいてパーミッションを606にしておいてください。

CRON呼びだし用(setlog.pl)

#!/usr/bin/perl

use strict;

#ログファイルをサーバ内の絶対パスで記入
#もちろんそれぞれの環境にあわせる
my $logfile = '/home/kiryuu/www/test/2008.dat';	

#リストファイルをサーバ内の絶対パスで記入
#もちろんそれぞれの環境にあわせる
# データの構成は、日付,総数,前日との差
my $datfile = '/home/kiryuu/www/test/list.dat';

#リストファイルを読み込む
open(IN,$datfile);
my @list = <IN>;
close(IN);
# @listにはアドレスファイルの中身が1行ごとに入っている

#ログファイルを読み込む
my @log;
if(-e $logfile){
	open(LOG,$logfile);
	@log = <LOG>;
	close(LOG);
}

# @logを分解
my(%dat,%all,%diff) =();
foreach(@log){
	my($t1,$t2,$t3) = split("\,",$_);
	$dat{$t1} = $t1;
	$all{$t1} = $t2;
	$diff{$t1} = $t3;
	}
# %datには日付、%allには総数、%diffには前日との差が入っている
# %datはなくてもよいが、後々何かに使えるかもしれない
# ハッシュのキーは日付

# 日付をソートする
my @sdays = sort({$a <=> $b} keys(%all));
# @sdaysには日付が昇順に入っている

# 今日の日付を取得する
$ENV{'TZ'} = 'JST-9';
my ($mday, $mon, $year) = ( localtime(time) )[3..5];
my $today = sprintf( "%04d/%02d/%02d" , $year + 1900, $mon + 1, $mday);
# 今日の日付がYYYY/MM/DDの書式で$todayに入っている

# リストの総数を取得する
my $all_day = scalar(@list);
# $all{今日の日付}に@listの数が入る。
# = @list や = $#list+1 でも可

# 前日との差を取得する
my $diff_day = $all_day - $all{$sdays[$#sdays]};
# $sdays[$#sdays]は@sdaysの最後の日付。
# %allには総数が格納されているので、
# $all{最後の日付}には最終日の総数が入る。
# これを、今日の総数から引くと差が出る。
#
# なぜ差も記録するか=>
#	何らかの事情でログファイルを編集して古いデータを削除しても
#	先頭の日付で前日との差を表示させるため

# 書き込むデータを作成
my $wdat = join(',',$today,$all_day,$diff_day) . "\n";

# ログファイルを追記モードで開く。ついでに書く
open(LOG,">>$logfile");
print LOG $wdat;
close(LOG);
chmod 0666,$logfile;

# 終了する
exit();

表示用CGI(showlog.cgi)

#!/usr/bin/perl

#ログファイル
#こっちは相対パスでも大丈夫
my $logfile = './2008.dat';

# ハッシュ変数を定義
my(%day,%all,%diff) = ();

# ログファイルを読み込んでハッシュに格納
open(LOG,$logfile);
my $tmp;	#使い捨ての変数
while($tmp = <LOG>){
	#改行文字を取り除く
	chomp $tmp;
	#使い捨て変数にログの内容を分割して格納
	my($t1,$t2,$t3)=split("\,",$tmp);
	# $t1(日付)をキーにハッシュ変数に代入
	$day{$t1} = $t1;
	$all{$t1} = $t2;
	$diff{$t1} = $t3;
	}
close(LOG);
# %day,%all,%diffにそれぞれ値が入った




#日ごとの部分のHTMLソース作成
#ハッシュを日付順にソートして、前日との差分を計算する
my @sdays = sort({$a cmp $b} keys(%all));
#日付で回す。$_には日付が入る
my @src_day = ();	#HTMLソースの種リスト
foreach(0 .. $#sdays){
	#前日との差を取得する
	#はじめのデータの場合は%diffを用い、それ以外の場合は前日のデータとの差を用いる
	my $diff_t;
	if($_ == 0){
		$diff_t = $diff{$sdays[$_]};
		}else{
		$diff_t = $all{$sdays[$_]} - $all{$sdays[$_ - 1]};
		}
	push(@src_day,"<tr><td align=\"right\">$sdays[$_]</td><td align=\"right\">$diff_t</td><td align=\"right\">$all{$sdays[$_]}</td>\n");
	}

#日付部分のHTMLソースを完成させる
my $html_day = <<'_HTML_';
<table border>
<tr>
<th>日付</th>
<th>増減数</th>
<th>保有数</th>
</tr>
_HTML_
#リストを逆順(新しい方が上)にしてからソースに追加
foreach(reverse(@src_day)){
	$html_day .= $_;
	}
#テーブルタグを閉じます
$html_day .= '</table>';


#月のデータのソース作成
# @sdaysは使い回す
# %day,%all,%diffも使い回す
# 考え方:前月の最終日の総数-今月の最終日の総数=差

#月のハッシュを作成
my %m_hash = ();
foreach(@sdays){
	$_ =~ /^(\d{4}\/\d{2})\//;
	$m_hash{$1} = $1;	#重複分は上書きされる
	}

my %m_all = ();

#それぞれの月の最終日を取り出す
#まず、月に合致する日付を取り出す
foreach(keys %m_hash){
	my $month = $_;
	my @tmp;
	foreach(@sdays){
		if($_ =~ /^$month/){
			push(@tmp,$_);
			}
		}
	# @sdaysは以前にソートされているので、
	# @tempの最後の値がその月の最終日
	$m_all{$month} = $all{$tmp[$#tmp]};
	}
# これで、%m_allには、それぞれの月の最終日の総数が入った

# 月をソートする
my @smonth = sort({$a cmp $b} keys(%m_all));
# @smonthには、月が昇順で入っています。

# 前月との差を求めつつソースも作る。
# 但し、最初の場合は「--」とする。
my @src_month = ();
foreach(0 .. $#smonth){
	my $m_diff_t;
	if($_ == 0){
		$m_diff_t = '--';
		}else{
		$m_diff_t = $m_all{$smonth[$_]} - $m_all{$smonth[$_ - 1]};
		}
	push(@src_month,"<tr><td align=\"right\">$smonth[$_]</td><td align=\"right\">$m_diff_t</td><td align=\"right\">$m_all{$smonth[$_]}</td>\n");
	}

#月部分のHTMLソースを完成させる
my $html_month = <<'_HTML_';
<table border>
<tr>
<th>日付</th>
<th>増減数</th>
<th>保有数</th>
</tr>
_HTML_
#リストを逆順(新しい方が上)にしてからソースに追加
foreach(reverse(@src_month)){
	$html_month .= $_;
	}
#テーブルタグを閉じます
$html_month .= '</table>';



## HTMLにはき出します
$html_src = <<"_HTML_";
Content-type: text/html; charset=Shift_JIS

<html>
<body>
<h2>なんかタイトルとか</h2>
<hr>
◆月毎
$html_month
<hr>
◆日毎
$html_day
<hr>
</body>
</html>
_HTML_

print $html_src;

exit();

サブルーチンも使わず、上から下までダ~っと処理しているんで、長くなってすいません。

Templateモジュールが使えるなら、tkyk3さんの回答の方がスッキリします。

id:icta

早々の回答ありがとうございます。

早速、試してみたところ昨日23時59分にアドレス保有数を取得することができました。

本日同時刻に増減数を取得でき、希望通りの動作を確認しましたら改めてご報告いたします。

2008/02/22 03:43:36
  • id:tezcello
    数えた行数を書き出す先は、固定ファイル名? 一日一ファイル名?

    固定ファイルの場合は、当日のデータを上書? あるいは追加?


    cron で行数を書き出すだけでなく、毎月用、毎日用のページも作ってしまうってのは?

  • id:kiryuu
    ブラウザから表示できるようにするのは、1日あるいは1月単独のデータでしょうか。

    それとも、
    2月1日分
    2月2日分
    2月3日分
    2月4日分
    2月5日分
    2月6日分
      ・
      ・
      ・
    と、表示していきたいということでしょうか。

    また、
    日付    増減数  アドレス保有数
    2007/2/22   -5   3000
    は、「2/22中にアドレス保有数は5件減って、2/22が終わる時点(正確には2/22 23:59)で3000件ある」という解釈でよろしいでしょうか。

    #CRONでは日ごとの保有数をログファイルに記録して、別のCGIでログファイルを表示させるのがいいかと思います。
    #ログをローカルマシンにダウンロードして参照するのが前提なら、CRON作業の際にHTMLファイルを作成するという方法もあります。
  • id:icta
    説明不足が多くて申し訳ありませんでした。

    最終的な目的は、ブラウザで▼次のように日々、月々の数値を表示させることです。
    http://www.kent-web.com/cgi/dayxmgr.cgi
    http://www.kent-web.com/count/dayx.html

    表示する内容はブラウザで見ることができるよう、▼次のようにします。
    日、月が改まる度に新しい行が上に追加されます。

    ◆月毎
    <table>
    <tr>
    <th>日付</th>
    <th>増減数</th>
    <th>保有数</th>
    </tr>
    <tr>
    <td>2007/4</td>
    <td>100</td>
    <td>3280</td>
    </tr>
    <tr>
    <td>2007/3</td>
    <td>-20</td>
    <td>3180</td>
    </tr>
    <tr>
    <td>2007/2</td>
    <td>300</td>
    <td>3200</td>
    </tr>
    </table>

    ◆日毎
    <table>
    <tr>
    <th>日付</th>
    <th>増減数</th>
    <th>保有数</th>
    </tr>
    <tr>
    <td>2007/2/22</td>
    <td>-5</td>
    <td>3000</td>
    </tr>
    <tr>
    <td>2007/2/21</td>
    <td>20</td>
    <td>3005</td>
    </tr>
    <tr>
    <td>2007/2/20</td>
    <td>30</td>
    <td>2985</td>
    </tr>
    </table>


    >数えた行数を書き出す先は、固定ファイル名? 一日一ファイル名?
    >固定ファイルの場合は、当日のデータを上書? あるいは追加?

    よくわかりませんが、http://www.kent-web.com/count/dayx.htmlに倣うのであれば数えた行数を書き出す先は固定ファイル名が良いと思います。
    上記ではday.dat、mon.datとなっており▼次のような内容になっています。

    ・day.dat
    02/01 (Fri)<>1190<>
    02/02 (Sat)<>1044<>
    02/03 (Sun)<>1035<>

    ・mon.dat
    2006/04<>32951<>
    2006/05<>34456<>
    2006/06<>33056<>


    >cron で行数を書き出すだけでなく、毎月用、毎日用のページも作ってしまうってのは?

    cronの機能をあまりよくわかっていないのかもしれませんが、cronはCGIを決められた時間に作動させるために使用すると考えていました。
    日毎、月毎のページは分けるよりもhttp://www.kent-web.com/cgi/dayxmgr.cgiのように同じページにあった方が見やすいかなと思っています。


    >ブラウザから表示できるようにするのは、1日あるいは1月単独のデータでしょうか。それとも、
    >2月1日分
    >2月2日分
    >2月3日分

    http://www.kent-web.com/cgi/dayxmgr.cgiのようにデータは上書きせず日毎、月毎に保存したいと思います。
    このURLでは日毎が翌月になると消えてしまいますがすべての日毎のデータを残したいと思います。


    >「2/22中にアドレス保有数は5件減って、2/22が終わる時点(正確には2/22 23:59)で3000件ある」という解釈でよろしいでしょうか。

    はい、そのとおりです。▼以下のように考えております。
    2/22の増減数 = 2/22 23:59の保有数 - 2/21 23:59の保有数


    >#CRONでは日ごとの保有数をログファイルに記録して、別のCGIでログファイルを表示させるのがいいかと思います。
    >#ログをローカルマシンにダウンロードして参照するのが前提なら、CRON作業の際にHTMLファイルを作成するという方法もあります。

    CRONはCGIを起動するために使用するつもりでした。
    ログをローカルにダウンロードすることは日毎データが大きくなったときに手作業で保存すればよいと考えておりました。
    CRON作業の際にHTMLファイルを作成するならこんなに便利なことはないと思います。
    ただ製作が複雑になり時間がかかるように思われますので基本的な機能だけでも十分だと思います。


    以上で説明不足の点などありましたらご指摘ください。
    それではよろしくお願いいたします。
  • id:kiryuu
    回答ありがとうございます。あと2点教えてください。

    ・Perlのバージョンはいくつでしょうか。
    (いまどき4ということはないでしょうが、念のため確認させてください)

    シェルログイン(telnet or SSH)ができるならログインして、
    perl -v
    と打ってみてください。

    シェルログインができないのでしたら、

    #!/usr/bin/perl
    my $ver = `perl -v`;
    print "Content-type: text/plain\n\n";
    print $ver;
    exit();

    をCGIファイルとして作成しサーバにアップしてパーミッションを705か755に設定してブラウザから呼び出してみてください。(勿論、先頭のperlのパスは適切なものに変更してください)
    (「`」はシングルクォート「'」とは別物です。通常でしたら、Shiftキーを押しながら@キーで入力できます。)
     このスクリプトは、OSコマンド(perl -v)を``で実行し、その結果を$verに格納して、テキストとして内容をはき出します。


    This is perl, v5.8.6 built for i386-linux-thread-multi

    Copyright 1987-2004, Larry Wall

    Perl may be copied only under the terms of either the Artistic License or the
    GNU General Public License, which may be found in the Perl 5 source kit.

    Complete documentation for Perl, including FAQ lists, should be found on
    this system using `man perl' or `perldoc perl'. If you have access to the
    Internet, point your browser at http://www.perl.org/, the Perl Home Page.

    こんな表示が出てくると思われます。
    先頭行のThis is perl, v5.8.6(この場合は5.8.6)がバージョンです。
    両方だめな場合(シェルログインができない、システムコール関数も許可されていない)はサーバ管理会社にお問い合わせください。

    ・出力するHTMLファイルの文字コードを教えてください(EUC-JP or Shift_JIS or utf-8 ?)
  • id:icta
    お力添えありがとうございます。
    いつも丁寧に教えていただいて大変感謝しております。

    >Perlのバージョンはいくつでしょうか。

    サーバーはsakuraを利用しており、サーバー情報にPerl 5.8.8と記載されていました。

    >出力するHTMLファイルの文字コードを教えてください

    文字コードはShift_JISを使っております。

    以上で回答になっておりますでしょうか。
    もし説明不足の点などありましたらご指摘ください。
    それではよろしくお願いいたします。
  • id:tkyk3
    Template-Toolkit(Templateモジュール)がさくらで使えないようだったら、HTML::Templateモジュールで書き直すのがいいかもしれませんね。テンプレートにしておくと、見せ方の変更が楽になるのでおすすめなんですがねぇ…。その場合はちょっと書き直してみようかと思います。
  • id:tkyk3
    もはや意味ないもしれませんが、一応HTML::Template版です。

    log.cgi
    ----
    #!/usr/bin/perl
    # HTML::Template版
    use strict;
    use warnings;
    use HTML::Template;

    my $address_filename = 'list.dat'; #読み込むメールアドレスリスト
    my $log_filename = 'log.dat'; #ログを記録するファイル名
    my $template_filename = 'template.tmpl'; #テンプレートファイル名
    my $html_filename = 'logview.html'; #ログHTMLファイル名

    my $template = HTML::Template->new(filename => $template_filename);

    #アドレスファイルを読み込む
    open(IN,"$address_filename");
    my @data = <IN>;
    close(IN);

    #今日の日付を取得
    $ENV{'TZ'} = "JST-9";
    my ($mday, $mon, $year) = ( localtime(time) )[3..5];
    my $today = sprintf( "%04d/%02d/%02d" , $year + 1900, $mon + 1, $mday); #今日の日付

    my $list_num = @data; #リスト数
    my $log_data = join( ',' , $today, $list_num ); #書き込むデータを生成

    #ログファイルを読み込む
    open(IN,"$log_filename");
    my @log_datas = <IN>;
    close(IN);

    push(@log_datas, $log_data); #今日の状況を追加する
    my @daily_logs;
    my @monthly_logs;

    foreach (0 .. $#log_datas) {
    ($daily_logs[$_]->{date}, $daily_logs[$_]->{num}) = split(/,/, $log_datas[$_]);
    }

    my ($month_diff, $month);
    foreach (0 .. $#log_datas) {
    $month = $daily_logs[$_]->{date};
    $month =~ s/\/\d{2}$//;
    if ( $month ne $month_diff && $_ > 0 ) { #月が変わったら
    push(@monthly_logs, { date => $month_diff, num => $daily_logs[$_ - 1]->{num} } );
    }
    elsif ($_ == $#log_datas) { #現時点で最後の日付
    push(@monthly_logs, { date => $month, num => $daily_logs[$_]->{num} } );
    }
    $month_diff = $month;
    }

    #ログファイルに追記保存
    open OUT,">>$log_filename";
    print OUT "$log_data\n";
    close OUT;

    balance(\@daily_logs);
    balance(\@monthly_logs);
    @daily_logs = reverse( @daily_logs ); #日付の新しい順にする
    @monthly_logs = reverse( @monthly_logs ); #日付の新しい順にする

    #テンプレートをもとにHTML保存
    $template->param(
    daily => \@daily_logs ,
    monthly => \@monthly_logs ,
    );
    open OUT,">$html_filename";
    $template->output(print_to => *OUT);
    close OUT;

    #--------------------------------------------------------------
    #増減を追記
    sub balance {
    my $log_ref = shift;
    my @output = @{ $log_ref };

    foreach (0 .. $#output) {
    if ( $_ > 0 ) { #2日目以降は増減を計算
    my $yesterday_num = $output[ $_ - 1 ]->{num};
    my $today_num = $output[ $_ ]->{num};
    $output[ $_ ]->{balance} = $today_num - $yesterday_num;
    }
    else { #最初は純増
    $output[ $_ ]->{balance} = $output[ $_ ]->{num};
    }
    }
    }

    -------

    template.tmpl(テンプレートファイル)
    -------
    <html>
    <head>
    <meta http-equiv="Content-Type" content="text/html;">
    <title>ログ集計</title>
    </head>
    <body>

    <h2>◆月毎</h2>
    <table>
    <tr>
    <th>日付</th>
    <th>増減数</th>
    <th>保有数</th>
    </tr>

    <TMPL_LOOP NAME="monthly">
    <tr>
    <td><TMPL_VAR NAME=date></td>
    <td><TMPL_VAR NAME=balance></td>
    <td><TMPL_VAR NAME=num></td>
    </tr>
    </TMPL_LOOP>
    </table>

    <h2>◆日毎</h2>
    <table>
    <tr>
    <th>日付</th>
    <th>増減数</th>
    <th>保有数</th>
    </tr>
    <TMPL_LOOP NAME="daily">
    <tr>
    <td><TMPL_VAR NAME=date></td>
    <td><TMPL_VAR NAME=balance></td>
    <td><TMPL_VAR NAME=num></td>
    </tr>
    </TMPL_LOOP>
    </table>

    </body>
    </html>

    -------

    便利でも使えなければ意味がないですよね。ご迷惑をお掛けしました。
  • id:icta
    kiryuuさん、tkyk3さんいろいろありがとうございました。
    期待通りの動作を確認しました。
    お手数をおかけいたしました。
    いろいろな方法があるものだと感心いたしました。
    手作業でやっていたことを自動化できて本当にうれしいです。
    お二人のお力添えに大変感謝しております

この質問への反応(ブックマークコメント)

「あの人に答えてほしい」「この質問はあの人が答えられそう」というときに、回答リクエストを送ってみてましょう。

これ以上回答リクエストを送信することはできません。制限について

絞り込み :
はてなココの「ともだち」を表示します。
回答リクエストを送信したユーザーはいません