51回php勉強会

東京で開催された51回目のphp勉強会に参加してきた。

場所は千駄ヶ谷駅から徒歩10分ぐらいのところ。

3月26日(金)22:00 高速バスに乗りつつ東京を目指す

3月27日(土)05:30 池袋到着。漫画喫茶で時間をつぶす。ついでに会場の確認。

同13:00 勉強会の会場へ向けて出発

13:15 千駄ヶ谷駅に到着。外苑らしきものを左手にまっすぐすすむ。今日は結構暖かい。歩くと汗ばむ。

13:45 まだつかない。ここはどこ?渋谷区とか書いてある。会場は新宿区だったはず。駅から北に行くべきを南に行ってた。

14:30 ようやく会場到着。普段歩くことすらしないからまじでしんどい。自己紹介とか終わってたし。みんなノートパソコンとか開いてる。自分も持ってきたけどネット環境ないしメモでいいや、って思っちゃう。

nekogetさんのcodeigniterによるデバッグ方法をやってた。前の方に座ったんだけど目が悪くてコードが見えない。悲しい。codeigniterって最近よく耳にする。是非使ってみようと心に誓う。帰ってきてから日本語の公式とか見てみたけど、使い方よくわかんなかった。スライドはわくわくさせてるんだけど、書籍でも買って一通りやらないとわかんないっぽい。

14:50? riafさんのrhaco2について。らこって読むんだ。rhinoとかひのって読むのかな。symphonyをめっちゃ敵視してた。そんなに言われるとsymphony使ってみたくなる。でもその前にcakeを使えるようにしたいんだ・・・。rhaco2については拡張性が豊かなオブジェクト群、って印象を受けた。ちょうどこの勉強会のあとで、xmlに対しての処理を行うコードを書いてたんだけど、ある子オブジェクトがあり複数のメンバ変数があるような状況で、そのオブジェクトの引き算を実装したかったんだけど、こんなのがrhaco2を使えば簡単なんだろうなぁ、って思った。結局使ってないのがダメだけど。キーワードjson/yaml

15:40? sotarokさんによるopenpear。スライドシェアにこの日のスライドが上がってるらしい。pearが厳格すぎて、新規にプロジェクト作る場合、かぶってるプロジェクトが無いかとか、規約違反なコード書いてたら直せとか、投票に通らないだめとかいろいろうるさいから、そこを回避するためのものらしい。赤いペアが印象的。キーワードはgit, pearhub, coderepos

16:30? TOMさんによるBEAR。やじうまWATCHとかされてるらしい。あとで懇親会の時隣になったんだけど、TOMさんだってわかんなかった。目が悪いせいでなんか遠くから見たらもっと年配の方に見えてましたごめんなさい。リソース指向まじさいこうって方でした。1ページ->1クラスな対応らしい。BEARプロジェクトページをみてねよくできてるから、だそうです。キーワード DI、フロントコントローラ

17:00? hnwさんによる64bitphpの罠。主にunixt時間で困りますよね的な。現在だと1900年からいけますけど、64bitだとうん京年までいけますよねー、だそうです。エポックタイムな1970年じゃないんですか、って懇親会で聞いたら、負の数いけるから1900年までさかのぼれるんですよ、だそうです。初めて知りましたへー。キーワード、PHP_INT_MAX

18:00? やきにくで懇親会。隅っこに陣取らせてもらって颯爽と日本酒を戴いて酔っ払いました。みなさん親しみやすくていろいろとお話させてもらえてうれしかったです。酔っ払いすぎて変なことしてないかあとで心配になりました。

???? 二次会に行く。もうよく覚えてない。店員が中華の人で絡んだ覚えががが。

21:00? なんとかして浅草着。電車で寝てた気がする。

24:30? 友達の家に着。楽しく会話しながら就寝。

お疲れ様でした。

gusagiさんお疲れ様です。二回目の参加ですがとても楽しかったです。また是非行かせてもらいます。

会場を提供してくださったトライコーンさんありがとうございます。いつかうちの会社も会場提供できるような会社になったらいいなぁ!

トラックバックってつけたこと無いけどどうやるんだろう。

jQuery+IEで$(window).mousemove(

某サイトでマウスの座標を得るJavascript書いてたけど、バグというか何と言うかちょっとハマったので。
jQuery使ってて画面内でのマウスの座標を得る場合

$(window).mousemove(function(e){
  pos = e.pageX;
  ...
  ...
});

とかやって取得してたけど、ググってみたらpageXはIEでサポートしてないとか書いてある所が何個か。けど

$(document).mousemove(function(e){
  pos = e.pageX;
  ...
  ...
});

ってやったら取得出来た。意味が分からない。jQueryオブジェクトに対してだと違うんだろうか。

nicoPlayerの広告アクセスロジックについて

ソースコードを見てようやく思い出したのでメモ。

各nicoサイト用の広告サイトを複数定義出来る。
各nicoサイトにレートを設定して、ランダムに1つのnicoサイトを選び出す。
選び出されたnicoサイトに定義してある広告サイトにアクセスする。
リファラは広告サイト毎に定義出来る。
プレイヤーが起動したときに広告にアクセスする。
前回広告にアクセスしてから24時間が経過しているか、もしくは6割の確率でアクセスする。

ソースコードはnicoLib\src\nicovide\adの中にある。
adAccessorがadBOTを作成する。adBOTがadAnalyzer_*を作成する。*はadAccessorのURLLISTのadsのtypeを用いる。
adsのurlにアクセスを行って、adAnalyzerがhtmlを解析してurlを返して再度アクセスを行う。これをadAnalyzerに定義してある正規表現の配列の数だけ行う。

nicovidaemonでshm_put_var Failedが連発していた問題について

php_error.logに以下のエラーが表示されていた。
[25-Mar-2010 20:40:02] PHP Warning:  shm_put_var(): not enough shared memory left in /usr/home/nicovide/nicovide/daemonListen_class.php on line 415

OS側の共有メモリのサイズ設定が小さい可能性を疑って調べてみた。
naname@madison<122>sysctl -a | grep shm
kern.ipc.shm_allow_removed: 0
kern.ipc.shm_use_phys: 0
kern.ipc.shmall: 8192
kern.ipc.shmseg: 128
kern.ipc.shmmni: 192
kern.ipc.shmmin: 1
kern.ipc.shmmax: 33554432

これらのパラメータはカーネルのオプションでも指定可能っぽい。/usr/local/sys/conf/NOTESに以下の記述があった。
# Maximum number of shared memory pages system wide.
options         SHMALL=1025

# Maximum size, in bytes, of a single System V shared memory region.
options         SHMMAX=(SHMMAXPGS*PAGE_SIZE+1)
options         SHMMAXPGS=1025

# Minimum size, in bytes, of a single System V shared memory region.
options         SHMMIN=2

# Maximum number of shared memory regions that can be used on the system
# at one time.
options         SHMMNI=33

# Maximum number of System V shared memory regions that can be attached to
# a single process at one time.
options         SHMSEG=9

/usr/src/sys/i386/conf/GENERICにはこれらは定義されていなかったので、sysctlの値がどう決定されたのかは不明。
変更する必要があるのであれば、kern.ipc.shmallとkern.ipc.shmmaxを設定すれば良さそう。

しかし問題になったmadisonには30M近く割り当てられていた。そんなに消費するはずは無いと思ったので、実際に使われているサイズを調べてみた。
http://www.jp.freebsd.org/cgi/mroff.cgi?sect=1&cmd=&lc=1&subdir=man&dir=jpman-5.4.0%2Fman&man=ipcs

Shared Memory:
T           ID          KEY MODE        OWNER    GROUP    CREATOR  CGROUP         NATTCH        SEGSZ         CPID         LPID ATIME    DTIME    CTIME
m        65536          488 –rw-rw-rw- root     wheel    root     wheel               0        10000          669          669 10:32:29 10:32:29 10:32:29
m      1310721          492 –rw-rw-rw- root     wheel    root     wheel               0        10000        22563        34774 21:39:40 21:39:40 18:35:38
m        65539          491 –rw-rw-rw- root     wheel    root     wheel               0        10000        41458        41458 16:11:00 16:11:00 16:11:00
m       983044          490 –rw-rw-rw- root     wheel    root     wheel               0        10000        28489        28486 21:39:37 21:39:37 20:42:31

SEGSZ(たぶんサイズ?)がすべて10000。これを見てピンと来た。

shm_attach — 共有メモリセグメントを作成またはオープンする

memsize
メモリのサイズ。省略した場合のデフォルトは php.inisysvshm.init_mem、あるいは 10000 バイトとなります。

nicovidaemonのコマンドが17+1(cmdcount)個。コマンド1個につき保存する項目が4つ(success,failed,timeout,time)。
18*4*PHP_INT_SIZE(環境によるらしいけどmadisonでは4)=288
到底10000バイトには及ばないけど、メモリの使い方にオーバーヘッドがあるのかもしれない。INT型以外も保存出来るようになってるし。

20000バイト確保するようにして様子を見ることにする。

wordpressで画像をはみ出さないようにする

投稿者が気をつければ良いだけだけど、気にしなくても良いとみんな嬉しい。
javascriptでjQuery使って書いた。チェックはしてない。

(function(){
  var modified = 610; // 納めるべき横幅をピクセルで指定(単位はいらない)
  var target = $("img.size-full");
  $(target).attr("width", modfied);
})();

知ってるブラウザの中では、横幅だけ指定すると自動で縦横比合わせてリサイズされます。

CactiでMySQLのレプリケーション情報をグラフ化する

Cactiでmysql-cacti-templatesを使うとMySQLのレプリケーション情報をグラフ化することが出来る。

レプリケーションサーバの状態を監視する必要があったので、mysql-cacti-templatesの中にあるGraph Template: X MySQL Replication GTのグラフを作成したが、どうも値が取れてないっぽかったので値の取得ロジックを探した。

X MySQL Replication GTに関連づけられているX MySQL Replication DTは、X Get MySQL Stats/MySQL Replication IMを用いる設定になっていた。GT,DT,IMはGraphTemplate, DataTemplate, DataImputMethodの略だろうか。
X Get MySQL Stats/MySQL Replication IMはss_get_mysql_stats.phpを呼び出すようになっていたので、ソースコードを追ってみた。

   # Get SHOW SLAVE STATUS, and add it to the $status array.
   if ( $chk_options['slave'] ) {
      $result = run_query("SHOW SLAVE STATUS", $conn);
      foreach ( $result as $row ) {
         # Must lowercase keys because different MySQL versions have different
         # lettercase.
         $row = array_change_key_case($row, CASE_LOWER);
         $status['relay_log_space']  = $row['relay_log_space'];
         $status['slave_lag']        = $row['seconds_behind_master'];

         # Check replication heartbeat, if present.
         if ( $heartbeat ) {
            $result2 = run_query(
               "SELECT GREATEST(0, UNIX_TIMESTAMP() - UNIX_TIMESTAMP(ts) - 1)"
               . "FROM $heartbeat WHERE id = 1", $conn);
            $status['slave_lag'] = $result2[0][0];
         }

         # Scale slave_running and slave_stopped relative to the slave lag.
         $status['slave_running'] = ($row['slave_sql_running'] == 'Yes')
            ? $status['slave_lag'] : 0;
         $status['slave_stopped'] = ($row['slave_sql_running'] == 'Yes')
            ? 0 : $status['slave_lag'];
      }
   }

$status[‘slave_running’]と$status[‘slave_stopped’]に正しく値が入ってほしい。
しかしスレーブが止まっていると$status[‘slave_lag’]の値が0になってしまうので、スレーブが遅延なしで動いてるのか止まっているのか判断がつかない。

$heartbeatをifで比較しているところが気になったので調べてみた。
スクリプトの先頭に$heartbeat  = ”;      # db.tbl in case you use mk-heartbeat from Maatkit.と書いてあった。
Maatkitとmk-heartbeatをサラッと調べてみたところ、Maatkitとはデータベースのツール群で、mk-heartbeatはその中の一つらしかった。

よく分からずに使ってみて分かったことは、mk-heartbeatはマスターサーバに1つのテーブルと1つの行を作成して、そこの行を常に現在時間で更新するツールらしい。
そうすることでスレーブサーバにmk-heartbeatが書き込んだ時間が送られて、それを現在時間と比較することでスレーブサーバの遅延を計ることが出来る。

Maatkitはportsからインストール出来る。
# portinstall databases/maatkit

mk-heartbeat用のテーブルをマスターサーバに対して作成する。
# mk-heartbeat –create-table -h hostname -D dbname –user username -p password –update
これでテーブルの作成と同時にカラムの更新が始まる。
テーブルがすでに作成済みの時にカラムの更新をする場合は以下の文を実行。
# mk-heartbeat -D dbname –update -h hostname -u username -p password

mk-heartbeatを常に実行するために起動スクリプトを書く。参考にした記事は以下の通り。
http://www.jp.freebsd.org/cgi/mroff.cgi?subdir=man&lc=1&cmd=&man=rc.d&dir=jpman-5.4.0%2Fman&sect=0
http://www.jp.freebsd.org/cgi/mroff.cgi?sect=8&cmd=&lc=1&subdir=man&dir=jpman-5.4.0%2Fman&subdir=man&man=rc.subr
http://www.jp.freebsd.org/cgi/mroff.cgi?sect=8&cmd=&lc=1&subdir=man&dir=jpman-5.4.0%2Fman&subdir=man&man=rcorder

作成したスクリプト。$nameにハイフンが使えなくてはまった。

#!/bin/sh

. /etc/rc.subr

rc_debug=1

name="mkheartbeat"
rcvar=`set_rcvar`
load_rc_config ${name}

: ${mkheartbeat_enable="NO"}
: ${mkheartbeat_user="root"}
: ${mkheartbeat_dbhost="localhost"}
: ${mkheartbeat_dbname="mysql"}
: ${mkheartbeat_dbuser="root"}
: ${mkheartbeat_dbpass="pass"}

command_interpreter="perl"
command_args="-D ${mkheartbeat_dbname} -h ${mkheartbeat_dbhost} -u ${mkheartbea\
t_dbuser} -p ${mkheartbeat_dbpass} --daemonize --update"
command="/usr/local/bin/mk-heartbeat"

run_rc_command "$1"

各サーバの時間がずれていては計測できないので注意。

Apacheからsyslogに送るログに関する決め事

syslog-ngでログを収集するときに、プログラム名に正規表現を用いて出力先のファイルを決めるようにした。
プログラム名を正規表現に一致するように設定する必要があるため、形式に一定のルールを決めてみた。

リバースプロキシサーバのログは、サイトへの全てのアクセスを記録するために、一つのファイルへ書き込むとする。
リバースプロキシサーバを複数用意したり、リバースプロキシサーバを担当するホストが変わったとしても、一つのファイルへ記録することで、サイトのアクセスログの見通しをよくするのが目的。
リバースプロキシサーバのプログラム名はhttpd-ドメイン名、httpd-ドメイン名-error(エラーログ)とする。

リバースプロキシからのアクセスを処理するバックエンドサーバ群(1台しかないけど)は、各サーバの処理状況を把握するためにホスト毎に記録する事とする。
バックエンドサーバのプログラム名はhttpd_backend-ドメイン名、httpd_backend-ドメイン名-error(エラーログ)とする。

リバースプロキシサーバのログのファイル名は、プログラム名-access.log、プログラム名-error.logとする。
バックエンドサーバ群のログのファイル名は、ホスト名-プログラム名-access.log、ホスト名-プログラム名-error.logとする。

例:
リバースプロキシサーバのプログラム名は
httpd-nicovide.jp
ログファイル名は
httpd-nicovide.jp-access.log

バックエンドサーバのプログラム名は
httpd_backend-nicovide.jp
ログファイル名は
lincoln-httpd_backend-nicovide.jp-access.log

yppasswdでパスワードを変更しようとしたらエラーがでた

l2tp.org%sudo yppasswd hogetan
Changing NIS password for hogetan
yppasswd: pam_chauthtok(): error in service module

nisで管理されているユーザのパスワードを変更するにはypcatpasswdを利用するが、どうにもエラーが出てしまって変更できない。

これは実は、pam_chauthokってやつがyppasswddへ変更したいよーって聞きに行くんだけど、そのデーモンが死んでいることが原因だったらしい。

I happened to find the problem so I’m reposting. rpc.yppasswdd was not
running. After I started the service back up it began working again.

Password change error — pam_chauthtok(): error in service module – BSD

yppasswddが起動しているか調べる。

l2tp.org%sudo /etc/rc.d/yppasswdd status
yppasswdd is not running.

起動していないので起動させる。rc.confに以下の行を追加。

nis_yppasswdd_enable=”YES”

起動させる。

l2tp.org%sudo /etc/rc.d/yppasswdd start

パスワード変更完了

l2tp.org%sudo yppasswd hogetan
Changing NIS password for hogetan
New Password:
Retype New Password: