2008/10/17(Fri)変数の展開の展開 +α
2008/09/17(Wed)Set-Cookieのpathについて
2008/09/17 18:22
設定するとき
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
仕様としては、自分で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で見るか……。
細かい統計はGoogle Analyticsで見るか……。
原因が分かった
開発者の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
ごらんのとおり、この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倍弱はある。
ちょっと時間ができたら双方を詳しく比べてこの問題を解決したいところである。今は時間がない。
2008/07/17(Thu)変数の展開の展開
2008/07/17 4:21
やりたいこと
「何らかの処理の結果、ある文字列が得られたとする。その文字列と同じ名前の変数名を取得したい」具体的には、リソースファイルに"この結果は$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とか付けると変数宣言の問題で面倒な事に。
どうしたかというと
なんとか引数に指定した変数を展開できないかなぁと思って調べていたら、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環境下で小細工しなくても普通に動く)