2008/09/17(Wed)Set-Cookieのpathについて

2008/09/17 18:22 Languages::Perl
Kerosoft@webのアナウンスをRSS配信するため、ウェブにコンパネを作っていた時、セッション管理用にCookieを使ったのだが、その時のメモ。

設定するとき

Set-Cookieのときのpathには注意しなくてはならない。
スクリプトの設置位置が、http://path-to-server/hogehoge.cgiだった場合、
Set-Cookie: CGISESSID=60b725f10c9c85c70d97880dfe8191b3; expires=Wed, 17-Sep-2008 21:16:22 GMT;
などとすると、デフォルトではその階層以下全てのディレクトリに対してCookieを送信してしまうので、ユーザー領域/~User/にも送ってしまうことになる。これは非常にまずい。

調べてみると、スクリプトを置く位置を自分以外がアクセスできないよう、/~hoge/以下に動かして、path=/~hoge/;とすれば安全と書いてあったが、今回のようにルートディレクトリに置きたい場合はどうするか。


結果的にいえば、こんな感じでいいようだ。
Set-Cookie: CGISESSID=60b725f10c9c85c70d97880dfe8191b3; expires=Wed, 17-Sep-2008 21:16:22 GMT; path=/hogehoge.cgi;
こうすれば、/hogehoge.cgi以下にはCookieが送られ、それ以外のアクセス(たとえば、/favicon.icoや/~user/hoge.htmlなど)へは送信されない。
このpathには、ディレクトリを指定するというような書き方をしているページが多々あったので、使い方を誤っているのかもしれないが、試した限りでは意図した動作をしているのでいいことにしようか…。
なお、別のユーザーが、/hogehoge.cgi/*等に対してアクセス権限を持っているとしたら意味がないので注意。そんなことはないと思うが。
ちなみに、/hogehoge.cgi部分は、$ENV{'SCRIPT_NAME'}で良いと思う。

削除のとき

削除する場合はexpiresに過去の値、たとえばThu, 01-Jan-1970 00:00:00 GMTを指定するが、これに関しても、pathを設定せねばならない。
Set-Cookie: CGISESSID=; expires=Thu, 01-Jan-1970 00:00:00 GMT; path=/hogehoge.cgi;
指定しない場合は、削除されない
ここに10分ほどハマってしまった……。

2008/07/31(Thu)adiaryのカウンタについて

2008/07/31 1:00 Languages::Perl
このModus Operandiがお世話になっているadiaryというBlog Systemはカウンタ機能を標準で持っていないので、3か月前くらいに自分で作ったのだが、たまたま友人から「ページビューが1増えたり2増えたりしてるぞ?」と報告をもらって色々調べてみた。


仕様としては、自分でPerl Moduleを一個作って/lib/Satsuki/に入れ、diary.user.skel/_sidebar.htmlのSystem Infoのとこにloadpmと値参照を加えるだけ。

とまぁ、そこまではいいのだが、やっぱりページビューを測るとなんかおかしい。
最初は自分の書き方が悪いのかと思ったのだが、どう考えてもforやwhileなどの繰り替えしを通らない部分に、カウント値の1upのコードを書いているので、おかしい……と悩んだ挙句、_sidebar.htmlが複数回呼ばれることがあるという結論に至った。

adiaryの中身をあまり詳しく見たわけではないのでよく分からないけど、1回しか呼ばれない場合と、2回呼ばれる場合がある模様。

そもそもカウンタはimgタグで対応してくれというのが作者の思惑なのかはわからないけど、とりあえずテキストカウンタにこだわりたいので現状のスタイルを保持して正しくカウントするには……と考え、PageViewの方はtime関数の戻り値が1以上ずれない限りカウントアップしないようにすることで対応した。
(ほんとは$$とかで対応しようかと思ったけど、speedy_backendが立ち上がりっぱなしなので、この手が使えない)

というわけで、同一時刻に複数からアクセスしても逆に1増えない、という状況になってしまったが、致し方ない。
細かい統計はGoogle Analyticsで見るか……。

原因が分かった 2008/07/31

開発者のnabe様から的確なコメントをいただき、一発で原因が分かりました。ありがとうございます。
どうやらブラウザが勝手に読みに行くfavicon.icoや存在しないRSSファイルを憶測で読みに行く時の404 Not Found画面でカウントアップしている感じでした。
<@ifexec(v.load_days, begin)>
<$c=loadpm("SimpleCounter")>
<@c.counter>
<$end>
404の"記事がありません"のメッセージ文を参考に、上記のように書き換えたことで、意図する動作になったかな。

2008/07/29(Tue)SpeedyCGIが大量起動

2008/07/29 0:47 Languages::Perl
このblogもそうだが、adiaryをサーバーに導入して、この公開blogと非公開blogを2つ運営している。
ごらんのとおり、このModus Operandiが公開blogである。
色々とadiary.conf.cgiの設定も違うから、ファイルを別個に分けてあるのだけど、どーも、moのほうだけ開くのが遅い。遅い。bf:遅い。
特にひどいのは記事をSubmitするときとか、管理メニューを開くとき。10秒くらい待たされることが多々。red:これはひどい。


何でだろうと思って、ターミナルを開くとこれまた重い。
Load Averageが5とか10とかになってやんの。どおりで重いわけだ……。

topをかけてみると、こんな感じ。*1
top - 00:51:48 up 88 days,  8:29,  1 user,  load average: 3.06, 2.15, 1.80
Tasks: 218 total,   5 running, 213 sleeping,   0 stopped,   0 zombie
Cpu(s): 98.5%us,  1.5%sy,  0.0%ni,  0.0%id,  0.0%wa,  0.0%hi,  0.0%si,  0.0%st
Mem:    515212k total,   349296k used,   165916k free,     8944k buffers
Swap:   787176k total,   388272k used,   398904k free,    58780k cached

  PID USER      PR  NI  VIRT  RES  SHR S %CPU %MEM    TIME+  COMMAND
18019 apache    20   0 30468  24m 2816 R 25.8  4.9   0:29.53 speedy_backend
17995 apache    20   0 29632  23m 2816 R 25.3  4.8   0:25.77 speedy_backend
18047 apache    20   0 28812  23m 2816 R 25.3  4.6   0:18.32 speedy_backend
17982 apache    20   0 28952  23m 2816 S 13.6  4.6   0:20.50 speedy_backend
18179 apache    20   0 25420  19m 2780 R  7.3  3.9   0:03.92 speedy_backend
 8566 apache    20   0  3912 1448 1444 S  0.0  0.3   0:00.01 speedy_backend
 8567 apache    20   0 25904 7580 2936 S  0.0  1.5   0:13.11 speedy_backend
16712 apache    20   0 26096 5728 2180 S  0.0  1.1   0:00.18 httpd
16719 apache    20   0 26100 5708 2176 S  0.0  1.1   0:00.13 httpd
17282 apache    20   0  3912 1832 1456 S  0.0  0.4   0:00.02 speedy_backend
17356 apache    20   0 26120 6804 3204 S  0.0  1.3   0:00.12 httpd
17647 apache    20   0 28352 9236 3216 S  0.0  1.8   0:00.66 httpd
18055 apache    20   0 26120 6784 3204 S  0.0  1.3   0:00.02 httpd
18155 apache    20   0  3640  800  652 S  0.0  0.2   0:00.00 adiary.speedy.c
18158 apache    20   0  3640  804  656 S  0.0  0.2   0:00.00 adiary.speedy.c
18159 apache    20   0  3640  808  656 S  0.0  0.2   0:00.00 adiary.speedy.c
18160 apache    20   0  3640  808  656 S  0.0  0.2   0:00.00 adiary.speedy.c
18161 apache    20   0  3640  796  652 S  0.0  0.2   0:00.00 adiary.speedy.c
18162 apache    20   0  3640  808  656 S  0.0  0.2   0:00.00 adiary.speedy.c
18163 apache    20   0  3640  808  656 S  0.0  0.2   0:00.00 adiary.speedy.c
18164 apache    20   0 26096 5076 1552 S  0.0  1.0   0:00.01 httpd
18171 apache    20   0  3640  792  652 S  0.0  0.2   0:00.00 adiary.speedy.c
18177 apache    20   0  3640  800  652 S  0.0  0.2   0:00.00 adiary.speedy.c
18178 apache    20   0  3640  796  652 S  0.0  0.2   0:00.00 adiary.speedy.c
18185 apache    20   0  3640  796  652 S  0.0  0.2   0:00.00 adiary.speedy.c
19629 apache    20   0 28716 7916 4552 S  0.0  1.5   0:05.22 httpd
19695 apache    20   0 28392 9724 4648 S  0.0  1.9   0:06.15 httpd
19726 apache    20   0 27052 7948 4444 S  0.0  1.5   0:03.95 httpd
19731 apache    20   0 28716 9468 4424 S  0.0  1.8   0:05.44 httpd
19744 apache    20   0 27940 9.9m 4720 S  0.0  2.0   0:04.48 httpd
19754 apache    20   0 27556 9748 4720 S  0.0  1.9   0:04.38 httpd
19760 apache    20   0 28376 9.8m 4608 S  0.0  2.0   0:06.34 httpd
19787 apache    20   0 27836 9.9m 4652 S  0.0  2.0   0:04.68 httpd
19813 apache    20   0 28696 9372 4296 S  0.0  1.8   0:05.04 httpd
22168 apache    20   0 28144 9284 4480 S  0.0  1.8   0:11.31 httpd
22170 apache    20   0 28136 8912 4624 S  0.0  1.7   0:08.38 httpd
22173 apache    20   0 27276 9036 4352 S  0.0  1.8   0:10.07 httpd
22175 apache    20   0 28720 8184 4648 S  0.0  1.6   0:14.24 httpd
26275 apache    20   0 28128 8724 4004 S  0.0  1.7   0:09.27 httpd
31115 apache    20   0 28708 9660 4476 S  0.0  1.9   0:09.31 httpd

apacheさんが大量にspeedyを起動しちゃって、backendが追いついていない感じ。
backendがアホみたいにCPUを食いつぶしているのが原因だろうと思って、一時的にspeedyの呼び出し引数に"-- -M5 -r10 -t3600"とか付けてみたんだけど、全然状況変わらず。


一方、非公開blogの方では同一バージョンを使用しているのに、全く
こういうことがない。speedyは常時2個くらい起動しっぱなしで、これ以上増えない。動作も快適。
が、moの方はリンクをクリックした拍子とかに10個も20個もバババーっと増えるのである。しばらくすると消える。

単にアクセス数の問題か……?否か……。
記事数ならば非公開blogの方がmoの10倍弱はある。


ちょっと時間ができたら双方を詳しく比べてこの問題を解決したいところである。今は時間がない。

*1 : 起動プロセス多すぎじゃね?とか、メモリが512MB(笑)とかいうのは置いといて……

2008/07/17(Thu)変数の展開の展開

2008/07/17 4:21 Languages::Perl
文字列処理にPerlほどすぐれた言語はない……と考えている今日この頃だが、ちょっとハマったので解決策をメモ。

やりたいこと

「何らかの処理の結果、ある文字列が得られたとする。その文字列と同じ名前の変数名を取得したい」

具体的には、リソースファイルに"この結果は$resultになります"のように埋め込んでおき、スクリプト実行時に変数$resultを代入して、"この結果は25になります"のように表示させたいわけだ。

今まで使っていた手法

リソースファイルをPerl化してしまってrequireすれば、同じ名前空間の変数で、すでに定義されているものは自動展開されるという仕様を使っていた。
埋め込む変数名ごとに正規表現で置換するような面倒な手法に比べると楽にできていたのだが、Perl化する手間とフォーマットが崩れるのが欠点。
拡張子がplになってしまうので*1、HTMLファイルのテンプレートを書いていたところで、vimなんかで読み込むとPerlの色づけしかしてくれなくて不便なのである。


実際どんな手順かというと、リソースファイルとして、
#!/usr/local/bin/perl

# requireされるとき自動展開するためにダブルクォートにしておく
$tmp = << "_EOM_";
この結果は$resultになります
_EOM_

# requireのため、1;は削除できない(結構面倒な仕様)
1;
という代入だけを行うスクリプトを別途用意し、
呼び出し側として、
#!/usr/local/bin/perl

$result = 5*5;
require 'resource.pl';
print $tmp;
のような手順を踏まなくてはいけない。自動展開されるとはいえ、結構めんどい。
また、$tmpや$resultという変数名は両ファイルで合わせておかなくてはならず、use strictとか付けると変数宣言の問題で面倒な事に。

*1 : そりゃ.htmlとか付けてもいいけど、中身perlだしね…不適切。

どうしたかというと

なんとか引数に指定した変数を展開できないかなぁと思って調べていたら、evalなんてコマンドがあった。
存在は知ってたけど、いまいち使いどころが分からなかったヤツ。

これを使うと実にスマートに書ける。
#!/usr/local/bin/perl

# シングルクォート囲みなのでこの時点では展開されないことに注意
$tmp = q|この結果は$resultになります|;
$result = 5*5;
$tmp =~ s/(\$\w+)/eval($1)/eg;
print $tmp.qq|\n|;
この書き方のポイントは、
  • $resultのような展開したい変数がいくつあっても動作すること
  • requireの必要がないこと = requireを使う場合の煩雑さがない
  • 展開する変数への代入を、読み込み後に行えること(requireの場合は、結果が先に分かってからrequireしないと代入されない)
  • (use strict環境下で小細工しなくても普通に動く)
注意として、↑のマッチングだと変数名のすぐ後に英数字が来ると誤爆するので、${result}のような形式のものだけ反応させるようにとか、適宜工夫することを推奨。