zt日記

書いているのは Kazuhiro NISHIYAMA a.k.a. ZnZです。
2001|09|10|11|12|
2002|01|02|03|04|05|06|07|08|09|10|11|12|
2003|01|02|03|04|05|06|07|08|09|10|11|12|
2004|01|02|03|04|05|06|07|08|09|10|11|12|
2005|01|02|03|04|05|06|07|08|09|10|11|12|
2006|01|02|03|04|05|06|07|08|09|10|11|12|
2007|01|02|03|04|05|06|07|08|09|10|11|12|
2008|01|02|03|04|05|06|07|08|09|10|11|12|
2009|01|02|03|04|05|06|07|08|09|10|11|12|
2010|01|02|03|04|05|06|07|08|09|10|11|12|
2011|01|02|03|04|05|06|07|08|09|10|
2012|04|05|06|09|

この日記にはツッコミを入れられます。 ツッコミを入れたい日付をクリックすると、フォームが現れます。

xreaでtDiaryを使う方法はxrea.com で tDiary を使う方法インストールメモXREA + tDiary + Namazuをどうぞ。


2010年02月01日(Mon)

DNSサーバのIPアドレス変更

ns.example.net のような名前を複数のゾーンのNSに指定しているので、名前を変えると面倒かなあと思ってIPアドレスだけ変更してみたが、netのNSに登録されているglue recordが古いままで更新されていない。

新しいサーバを古いIPアドレスに移動した方が良いのか、whois情報を同じ情報で登録し直してみるべきなのかよくわからない。


2010年02月02日(Tue)

incron で fetch_changesets

commit がないときまで cron で redmine の "Repository.fetch_changesets" を動かし続けるのは無駄だと思って、 incron を使ってコミットがあったときに fetch_changesets するようにしてみた。

流れとしてはまず subversion の post-commit hook の途中に

touch /home/redmine/committed-stamp

のような処理を埋め込み、 committed-stamp の owner を www-data にしておく (post-commit hook の実行権限のユーザで、この場合は mod_dav_svn 経由にしているので www-data になる)。

次に crontab(1) と同様に incrontab(1) で

/home/redmine/committed-stamp IN_CLOSE,IN_NO_LOOP /home/redmine/fetch_changesets.sh

のような内容を登録する。

fetch_changesets.sh は今まで cron で実行していたスクリプトを改造したもので、以下のような内容。 incron は vixie-cron と違って、出力をメールで送信してくれる機能はないようなので、リダイレクトして何か出力されていればメールするようにしてみた。

sleep は上の IN_NO_LOOP とあわせて連続で commit があったときに連続実行される回数を減らすために追加してみた。

$ cat fetch_changesets.sh
#!/bin/sh
cd "$(dirname "$0")"
if [ redmine != `id -un` ]; then
    echo $0: must run as redmine 1>&2
    exit 1
fi
sleep 10
exec >fetch_changesets.log 1>&2
if [ -d redmine ]; then
    cd redmine
    /opt/ruby-enterprise/bin/ruby script/runner "Repository.fetch_changesets" -e production
fi
if [ -s ../fetch_changesets.log ]; then
    mail -s fetch_changesets redmine < ../fetch_changesets.log
fi

2010年02月03日(Wed)

コメント抜き

rubyのワンライナーを見て、ワンライナーではあんまりrubyを使わないけど、正規表現はもうちょっとがんばれば条件1つだけで済ませられる(し strip もいらないのに)と思った。

ちなみにシェルのヒストリから取り出したコメント抜きにする例。 sources.list は行頭にしか「#」を使ってなかったけど、dovecot.conf は行の途中からもあったので空白を無視するようにしている。インデントにタブも使っていればタブも最初の文字クラスに入れれば良い。

egrep '^[^#]' /etc/apt/sources.list
egrep '^[ ]*[^ #]' /etc/dovecot/dovecot.conf

2010年02月04日(Thu)

IPアドレス交換

DNSサーバのIPアドレス変更 は影響範囲が把握しきれなくて難しそうだったので、新サーバと旧サーバのIPアドレスを交換することにした。

今のところ、交換したことによる悪影響は起きてなさそう。


2010年02月05日(Fri)

samba で homes 共有にだけつながらない

LDAP で認証統合しようとしている途中の Debian lenny のサーバで、普通の共有には認証したユーザでつながるのに homes 共有だけつながらないという現象が起きていた。

ログを見ると

passdb/passdb.c:lookup_global_sam_name(595)
  User ユーザ with invalid SID ユーザのSID
 in passdb

と出ていて、検索してみると setlocalsid すると直るという話があって試してみたが、変わらなかった。

エラーメッセージや検索して見つかった情報から、ドメインにするつもりはなくて LDAP を使いたかったために BDC っぽい設定氏にしていたことを思い出して、「domain logons = no」だったところを「domain logons = yes」にしてみると homes 共有にもアクセス出来るようになった。

これが正しい対処なのかどうかはわからないが、samba の設定はバージョンによる違いも多く、深追いするときりがなさそうなので、目的の範囲で問題なく動作していることが確認できれば良さそうに思った。


2010年02月06日(Sat)

[debian] apache2 の default の VirtualHost

先日の IP アドレスの交換で default の VirtualHost の「It works!」とかが検索エンジンに残るとまずいと思って、 http://ya.maya.st/d/200707a.html#p20070709_1_2 を参考にして「/etc/apache2/sites-available/default」に以下の設定をした。「/」なのがまずいのか、別ファイルを指定するのはうまくいかなかったので、直接 HTML を埋め込んだ。 エラーメッセージは 503 のデフォルトのメッセージの「The server is temporarily unable to service your request due to maintenance downtime or capacity problems. Please try again later.」から「 or capacity problems」を削って使った。

Redirect 503 /
ErrorDocument 503 "<html><head><title>503 Service Temporarily Unavailable</title></head><body><h1>Service Temporarily Unavailable</h1><p>The server is temporarily unable to service your request due to maintenance downtime. Please try again later.</p></body></html>"

まだ etch の apache 1.3 のサーバも残っていたが、そちらは ErrorDocument の末尾の「"」を削らないと「"」まで表示されてしまうと言うことになってしまっていた。


2010年02月07日(Sun)

ゲームは難しい?

社長が訊く「Wii・DSソフト おさがしガイド(仮称)」2. ソフトを買っても遊び方がわからない の「中からちっちゃいのが出てきた」の話とか「どうやって、DSの本体に入れるんだ?」とかもなんというか、そういう層にも売れているんだなあという感じだけど、あまりゲームをやらない人が「New スーパーマリオブラザーズ Wii」で World 4 あたりで進めなくなっているという話があって、一緒にやってみると、亀の甲羅をもてるということを知らなかったり、スピンジャンプが偶然出ることはあってもどうやって出すのかを知らなかったりと、簡単そうなゲームでも知っている人には当たり前で説明がいらないと思ってしまうことが多いということがわかった。

Business Media 誠:“よくできたゲーム”と“面白いゲーム”の違いとは?――マリオの父、宮本茂氏の設計哲学(前編) (5/5) の「やっぱりアクションゲームって好きな人じゃないと難しい」とか。


2010年02月08日(Mon)

ldaps の証明書の期限切れ

VMware Server のホストOS側は ldap://127.0.0.1/ で接続していたので影響はなかったが、ゲストOS側は ldaps://ldap.example.jp/ のように ldaps で接続していたので、証明書の期限切れに伴い、 libpam-ldap での認証が通らなくなってしまっていた。 そのまましばらくほっといていたら、 libnss-ldap での情報もとれなくなったようで、ローカルユーザしか使えなくなってしまった。 ldaps の証明書を更新しても、 nscd のキャッシュを消しても、すぐには使えるようにならなかったので、ゲストOSを再起動してみると直った。


2010年02月09日(Tue)

Rubyist Hotlinks

Ruby hotlinks のドメインがなくなっているなど、明らかに接続できなくなっているものをコメントアウトしたり、2chのを次スレに更新したりした。


2010年02月10日(Wed)

ML

fml は lenny でなくなっていて、 qwik も squeeze でなくなってしまうようなので、選択肢がどんどん減っていく。 mailman が無難そうなので、ちょっと VMware で試し中。

fml は1つのサーバで2つのドメインを動かしていたけど、1つの mailman のサーバで複数のドメインで使うのは、Web を片方だけ https とか出来なさそうで、ちょっと面倒そうに感じたので、1つのドメインに統合した方がいいのかもしれない。


2010年02月11日(Thu)

停電

http://b.hatena.ne.jp/entry/www.asahi.com/national/update/0212/OSK201002110143.html の時に2ビルでも少し停電したらしく、会社のサーバも影響を受けていた。

その影響で /etc/xen/auto にシンボリックリンクを作成し忘れているものがあったことに気づいた。 社内 DNS サーバになっているマシンがなぜか不調になっていて、/etc/resolv.conf で2個用意している DNS サーバの片方しか書いていないという設定の不備も発見できた。


2010年02月12日(Fri)

[debian] sid の起動周りが不調

Debian sid の grub-pc 1.98~20100128-1.1 でなぜかうまく起動できないので、コマンドラインで

insmod ext2
root (hd0,1)
cat /boot/grub/grub.cfg
linux /boot/vmlinuz-... root=grub.cfgで見えたもの
initrd /boot/initrd.img-...
boot

のように起動していたが、面倒になったので、以下のように squeeze の grub-pc に戻して、今の grub-pc は入れないようにした。

sudo aptitude install grub-pc/squeeze grub-common/squeeze
sudo aptitude forbid-version grub-common grub-pc

それとは別に #566532 - linux-image-2.6.32-trunk-686: kernel BUG at /tmp/buildd/linux-2.6-2.6.32/debian/build/source_i386_none/fs/quota/dquot.c:1398! - Debian Bug report logs と同じように quota を有効にしてると起動途中で止まるので、 linux-image-2.6.32-trunk-amd64 ではなく linux-image-2.6.32-2-amd64 で起動している。


2010年02月13日(Sat)

IRCnet 不調?

irc.media.kyoto-u.ac.jp が一時的に落ちたらしくなんか不安定だった。


2010年02月14日(Sun)

pam の設定

http://d.hatena.ne.jp/mono-hate/20090304/1236186343 経由で http://www.ubuntulinux.jp/getubuntu/releasenotes/810overview によると Ubuntu 8.10 から auth-clinet-config の代わりに pam-auth-update になっていたらしく、Debian では auth-clinet-config が入った状態でリリースされることなく、現状の testing (squeeze) には pam-auth-update が入っていた。

今までは、例えば libpam-tmpdir パッケージをインストールしても自分で /etc/pam.d/common-session に「session optional pam_tmpdir.so」のように設定を追加しないと有効にならなかったが、 pam-auth-update では (手動で pam.d 以下のファイルを書き換えていなければ) /usr/share/pam-configs/ 以下のファイルから自動で設定を更新してくれるので、 libpam-tmpdir なら以下のような感じになっていた。

$ cat /usr/share/pam-configs/tmpdir
Name: per-user temporary directories
Default: yes
Priority: 0
Session-Type: Additional
Session-Final:
 optional pam_tmpdir.so
$ grep -r tmpdir /etc/pam.d
/etc/pam.d/common-session-noninteractive:session        optional pam_tmpdir.so
/etc/pam.d/common-session:session       optional pam_tmpdir.so
$

現状の lenny では以下のように pam_localuser.so で分岐して pam_ldap.so と pam_unix.so を使って、 success=1 だと成功が残らないので pam_permit.so で成功を残すようにすると言う設定を自分でしている。

$ egrep '^[^#]' etc/pam.d/common-*
etc/pam.d/common-account:account        [success=1 default=ignore]      pam_localuser.so
etc/pam.d/common-account:account        [success=1 new_authtok_reqd=1 ignore=ignore default=die]        pam_ldap.so
etc/pam.d/common-account:account        required        pam_unix.so
etc/pam.d/common-account:account        required        pam_permit.so
etc/pam.d/common-auth:auth      [success=1 default=ignore]      pam_localuser.so
etc/pam.d/common-auth:auth      [success=1 new_authtok_reqd=1 ignore=ignore default=die]        pam_ldap.so
etc/pam.d/common-auth:auth      required        pam_unix.so nullok_secure
etc/pam.d/common-auth:auth      required        pam_permit.so
etc/pam.d/common-password:password      [success=2 default=ignore]      pam_localuser.so
etc/pam.d/common-password:password      required        pam_echo.so see http ...
etc/pam.d/common-password:password      requisite       pam_deny.so
etc/pam.d/common-password:password      required        pam_unix.so nullok obscure md5
etc/pam.d/common-password:password      required        pam_permit.so
etc/pam.d/common-session:session        [success=2 default=ignore]      pam_localuser.so
etc/pam.d/common-session:session        required        pam_mkhomedir.so skel=/etc/skel umask=0022
etc/pam.d/common-session:session        optional        pam_ldap.so
etc/pam.d/common-session:session        required        pam_unix.so
etc/pam.d/common-session:session        optional        pam_tmpdir.so

pam-auth-update では以下のように

  • pam_unix.so
  • pam_ldap.so

と順番に試してどれか成功すれば success=N で飛ばして pam_permit.so で、どれも成功しなければ pam_deny.so で終了という、現在 lenny で設定した方法に似た方法でやっているので、独自の設定にするよりも pam-auth-update に任せた方が管理が楽になって良さそうだと思った。 (pam_localuser.so でスキップするのに比べて、 pam_unix.so で認証失敗したときにも pam_ldap.so の認証を試されてしまうと言う違いはあるけれど)

$ egrep '^[^#]' /etc/pam.d/common-*
/etc/pam.d/common-account:account       [success=2 new_authtok_reqd=done default=ignore]        pam_unix.so
/etc/pam.d/common-account:account       [success=1 default=ignore]      pam_ldap.so
/etc/pam.d/common-account:account       requisite                       pam_deny.so
/etc/pam.d/common-account:account       required                        pam_permit.so
/etc/pam.d/common-auth:auth     [success=2 default=ignore]      pam_unix.so nullok_secure
/etc/pam.d/common-auth:auth     [success=1 default=ignore]      pam_ldap.so use_first_pass
/etc/pam.d/common-auth:auth     requisite                       pam_deny.so
/etc/pam.d/common-auth:auth     required                        pam_permit.so
/etc/pam.d/common-password:password     [success=2 default=ignore]      pam_unix.so obscure sha512
/etc/pam.d/common-password:password     [success=1 user_unknown=ignore default=die]     pam_ldap.so use_authtok try_first_pass
/etc/pam.d/common-password:password     requisite                       pam_deny.so
/etc/pam.d/common-password:password     required                        pam_permit.so
/etc/pam.d/common-password:password     optional        pam_gnome_keyring.so
/etc/pam.d/common-session:session       [default=1]                     pam_permit.so
/etc/pam.d/common-session:session       requisite                       pam_deny.so
/etc/pam.d/common-session:session       required                        pam_permit.so
/etc/pam.d/common-session:session       required        pam_unix.so
/etc/pam.d/common-session:session       optional                        pam_ldap.so
/etc/pam.d/common-session:session       optional pam_tmpdir.so
/etc/pam.d/common-session:session       optional                        pam_ck_connector.so nox11
/etc/pam.d/common-session-noninteractive:session        [default=1]            pam_permit.so
/etc/pam.d/common-session-noninteractive:session        requisite              pam_deny.so
/etc/pam.d/common-session-noninteractive:session        required               pam_permit.so
/etc/pam.d/common-session-noninteractive:session        required        pam_unix.so
/etc/pam.d/common-session-noninteractive:session        optional               pam_ldap.so
/etc/pam.d/common-session-noninteractive:session        optional pam_tmpdir.so
$

2010年02月15日(Mon)

[debian] etch のセキュリティサポート終了の日

etch のセキュリティサポート終了 の日だったが、まだちょっとだけ etch のサーバが残っているので、出来るだけすみやかに移行したい。


2010年02月16日(Tue)

mercurial とか

git にある程度なれたので、mercurial の使い方に悩む。

「git grep PATTERN」の代わりは無いんだろうかとか。とりあえず「hg grep -n -r tip PATTERN」にしてみたけどリビジョン部分がじゃま。


2010年02月17日(Wed)

rubygems のバージョン指定

rack 1.1.0 が入っていると radiant が動かなくなるので「gem uninstall rack -v 1.1.0」でアンインストールした。

調べてみると vendor/rails/actionpack/lib/action_controller.rb の「gem 'rack', '~> 1.0.0'」を書き換えるという対処もあるようだが、「~>」で互換性のあるバージョンアップは受け入れるようにしていて、わざわざ rack が 1.0.x ではなく 1.1.0 にして互換性がないと明示しているので、 1.1.0 と一緒に使わない方が良いと思った。


2010年02月18日(Thu)

WILLCOM

■ お客様に対しては、従前通りのサービスを継続して提供いたします。」ということのようなので、とりあえず気にせずそのまま使い続ける予定。


2010年02月19日(Fri)

[ruby] rvm

http://rvm.beginrescueend.com/ を使ってみたが、 cd を置き換えるなど、独自の挙動が多いので、普段の環境にそのまま入れるのには向かないと思った。


2010年02月20日(Sat)

[ruby] concov

concov を今度は毎日動かす予定の環境にインストール。

参考:

concov を分離ユーザでインストール。

まず専用ユーザを作成。

$ sudo adduser --disabled-login --no-create-home --shell /bin/false chkbuild
Adding user `chkbuild' ...
Adding new group `chkbuild' (1001) ...
Adding new user `chkbuild' (1001) with group `chkbuild' ...
Not creating home directory `/home/chkbuild'.
chkbuild のユーザ情報を変更中
新しい値を入力してください。標準設定値を使うならリターンを押してください
        フルネーム []:
        部屋番号 []:
        職場電話番号 []:
        自宅電話番号 []:
        その他 []:
Is the information correct? [Y/n]
$ sudo adduser --disabled-login --no-create-home --shell /bin/false concov
Adding user `concov' ...
Adding new group `concov' (1002) ...
Adding new user `concov' (1002) with group `concov' ...
Not creating home directory `/home/concov'.
concov のユーザ情報を変更中
新しい値を入力してください。標準設定値を使うならリターンを押してください
        フルネーム []:
        部屋番号 []:
        職場電話番号 []:
        自宅電話番号 []:
        その他 []:
Is the information correct? [Y/n]
$ sudo gpasswd -a concov chkbuild
ユーザ concov をグループ chkbuild に追加
$

インストール先の構成。

  • /home/concov - concov ユーザのホームディレクトリ
  • /home/concov/chkbuild - chkbuild インストール先
  • /home/concov/chkbuild/start-build-ruby-coverage - concov 用 start-build
  • /home/concov/chkbuild/tmp -> /home/chkbuild
  • /home/concov/concov - concov インストール先
  • /home/concov/concov/public/chkbuild -> /home/chkbuild/public_html/ruby-trunk-coverage
  • /home/concov/update.rb - concov 定期実行用プログラム
  • /home/chkbuild - chkbuild のホームディレクトリ
  • /home/chkbuild/build - chkbuild のビルド用ディレクトリ
  • /home/chkbuild/concov-data - concov のデータベース用ディレクトリ
  • /home/chkbuild/public_html - chkbuild の結果出力用ディレクトリ

インストール先作成。

$ sudo mkdir chkbuild
$ sudo mkdir -p concov/chkbuild/CVS
$ sudo chown -R concov:concov concov
$

chkbuild のインストール。

$ echo :pserver:anonymous@cvs.m17n.org:/cvs/ruby | sudo -u concov tee concov/chkbuild/CVS/Root
:pserver:anonymous@cvs.m17n.org:/cvs/ruby
$ echo chkbuild | sudo -u concov tee concov/chkbuild/CVS/Repository
chkbuild
$ cd /home/concov/chkbuild
$ sudo -u concov git cvsimport
Initialized empty Git repository in /home/concov/chkbuild/.git/
connect error: Network is unreachable
cvs rlog: CVS password file /home/concov/.cvspass does not exist - creating a new file
cvs rlog: Logging chkbuild
cvs rlog: Logging chkbuild/chkbuild
cvs rlog: Logging chkbuild/sample
cvs rlog: Logging chkbuild/setup
cvs rlog: Logging chkbuild/test
Counting objects: 2730, done.
Compressing objects: 100% (2707/2707), done.
Writing objects: 100% (2730/2730), done.
Total 2730 (delta 1973), reused 0 (delta 0)
Removing duplicate objects: 100% (256/256), done.

real    2m59.551s
user    0m10.793s
sys     0m20.445s
$ sudo -u concov ln -s /home/chkbuild tmp
$ sudo mkdir /home/chkbuild/build
$ sudo mkdir /home/chkbuild/public_html
$ sudo chown concov:chkbuild /home/chkbuild
$ sudo chmod 2755 /home/chkbuild
$ sudo chown chkbuild:chkbuild /home/chkbuild/build /home/chkbuild/public_html
$ sudo chmod 2775 /home/chkbuild/build /home/chkbuild/public_html
$

chkbuild にパッチをあてる。

$ sudo -H -u concov git checkout -b concov
Switched to a new branch "concov"
$ curl http://dame.dyndns.org/misc/misc/chkbuild-coverage-date.patch | sudo -H -u concov patch -p0
  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed
100  5593  100  5593    0     0  26836      0 --:--:-- --:--:-- --:--:--  259k
patching file rbcoverage.rb
patching file chkbuild/build.rb
Hunk #1 FAILED at 94.
1 out of 1 hunk FAILED -- saving rejects to file chkbuild/build.rb.rej
patching file chkbuild/main.rb
Hunk #1 succeeded at 58 (offset 26 lines).
patching file chkbuild/ruby.rb
Hunk #1 succeeded at 135 (offset 26 lines).
patching file chkbuild/svn.rb
Hunk #1 succeeded at 91 with fuzz 1 (offset 33 lines).
Hunk #2 FAILED at 108.
1 out of 2 hunks FAILED -- saving rejects to file chkbuild/svn.rb.rej
patching file sample/build-ruby-coverage
$ cat chkbuild/build.rb.rej chkbuild/svn.rb.rej
(略)
$ sudo vi chkbuild/build.rb chkbuild/svn.rb
(略)
$ sudo rm chkbuild/*.rej
$ sudo rm chkbuild/*.orig
$ echo /CVS | sudo -H -u concov tee -a .git/info/exclude
/CVS
$ echo /tmp | sudo -H -u concov tee -a .git/info/exclude
/tmp
$ sudo -H -u concov git status | cat
# On branch concov
# Changed but not updated:
#   (use "git add <file>..." to update what will be committed)
#
#       modified:   chkbuild/build.rb
#       modified:   chkbuild/main.rb
#       modified:   chkbuild/ruby.rb
#       modified:   chkbuild/svn.rb
#
# Untracked files:
#   (use "git add <file>..." to include in what will be committed)
#
#       rbcoverage.rb
#       sample/build-ruby-coverage
no changes added to commit (use "git add" and/or "git commit -a")
$ sudo -H -u concov git add .
$ sudo -H -u concov git status | cat
# On branch concov
# Changes to be committed:
#   (use "git reset HEAD <file>..." to unstage)
#
#       modified:   chkbuild/build.rb
#       modified:   chkbuild/main.rb
#       modified:   chkbuild/ruby.rb
#       modified:   chkbuild/svn.rb
#       new file:   rbcoverage.rb
#       new file:   sample/build-ruby-coverage
#
$ sudo -H -u concov git commit -v -m "apply http://dame.dyndns.org/misc/misc/chkbuild-coverage-date.patch"
Created commit 6b0e770: apply http://dame.dyndns.org/misc/misc/chkbuild-coverage-date.patch
 6 files changed, 83 insertions(+), 3 deletions(-)
 create mode 100644 rbcoverage.rb
 create mode 100644 sample/build-ruby-coverage
$

マージミスがあったのを修正したので commit の id が変わってしまったけど、パッチの内容。

$ sudo -H -u concov git show HEAD
commit d10009876d09074dc7917da96d300d1c03bdf2b9
Author: concov <concov@...>
Date:   Sat Feb 20 12:55:25 2010 +0900

    apply http://dame.dyndns.org/misc/misc/chkbuild-coverage-date.patch

diff --git a/chkbuild/build.rb b/chkbuild/build.rb
index e686500..72754be 100644
--- a/chkbuild/build.rb
+++ b/chkbuild/build.rb
@@ -120,7 +120,8 @@ class ChkBuild::Build
       raise "already built"
     end
     branch_info = @suffixes + dep_dirs
-    @start_time_obj = start_time_obj = Time.now
+    start_time_obj = $date ? Time.gm(*$date) : Time.now
+    @start_time_obj = start_time_obj
     @start_time = start_time_obj.strftime("%Y%m%dT%H%M%S")
     dir = ChkBuild.build_top + self.depsuffixed_name + @start_time
     r, w = IO.pipe
diff --git a/chkbuild/main.rb b/chkbuild/main.rb
index d638866..b19ab60 100644
--- a/chkbuild/main.rb
+++ b/chkbuild/main.rb
@@ -58,6 +58,10 @@ End
         t.update_option(:procmemsize => true)
       }
     }
+    o.def_option('--date NUM') {|date|
+      raise unless date[/\A(\d{4})(\d{2})(\d{2})\z/]
+      $date = [$1, $2, $3].map {|v| v.to_i }
+    }
     o.parse!
     begin
       Process.setpriority(Process::PRIO_PROCESS, 0, 10)
diff --git a/chkbuild/ruby.rb b/chkbuild/ruby.rb
index 2a73451..e8ea35e 100644
--- a/chkbuild/ruby.rb
+++ b/chkbuild/ruby.rb
@@ -135,6 +135,9 @@ End
             make_options["ENV:LD_RUN_PATH"] = "#{$'}/lib"
           when /\Aautoconf=/
             autoconf_command = "#{$'}/bin/autoconf"
+          when "coverage"
+            cflags << "-fprofile-arcs -ftest-coverage"
+            dldflags << "-Wl,-whole-archive -lgcov -Wl,-no-whole-archive"
           else
             raise "unexpected suffix: #{s.inspect}"
           end
diff --git a/chkbuild/svn.rb b/chkbuild/svn.rb
index 8324838..91e91dd 100644
--- a/chkbuild/svn.rb
+++ b/chkbuild/svn.rb
@@ -91,7 +91,8 @@ class ChkBuild::Build
         self.run "svn", "cleanup", opts
         opts[:section] = nil
         h1 = svn_revisions
-        self.run "svn", "update", "-q", opts
+        rev = $date ? "{%04d%02d%02d}" % $date : "HEAD"
+        self.run "svn", "update", "-q", "-r", rev, opts
         h2 = svn_revisions
         svn_print_changes(h1, h2, viewvc, rep_dir)
         self.run "svn", "info", opts_info
@@ -108,7 +109,8 @@ class ChkBuild::Build
           h1 = svn_revisions
         }
       end
-      self.run "svn", "checkout", "-q", url, working_dir, opts
+      rev = $date ? "{%04d%02d%02d}" % $date : "HEAD"
+      self.run "svn", "checkout", "-q", "-r", rev, url, working_dir, opts
       opts[:section] = nil
       Dir.chdir(working_dir) {
         h2 = svn_revisions
diff --git a/rbcoverage.rb b/rbcoverage.rb
new file mode 100644
index 0000000..c0219ec
--- /dev/null
+++ b/rbcoverage.rb
@@ -0,0 +1,60 @@
+require "coverage.so"
+
+Coverage.start
+
+ext = ENV["COVERUBY_EXT"] || ".rbcov"
+accum = ENV["COVERUBY_ACCUM"]
+accum = !accum || accum == "" || !(%w(f n 0).include?(accum[0]))
+pwd = Dir.pwd
+
+at_exit do
+  Dir.chdir(pwd) do
+    Coverage.result.each do |sfile, covs|
+      cfile = sfile + ext
+
+      writable = proc do |f|
+        File.writable?(f) || File.writable?(File.dirname(f))
+      end
+      unless writable[cfile]
+        cfile = cfile.gsub(File.PATH_SEPARATOR, "#")
+        next unless writable[cfile]
+      end
+
+      readlines = proc do |f|
+        File.read(f).force_encoding("ASCII-8BIT").lines.to_a
+      end
+
+      sources = (readlines[sfile] rescue [])
+
+      pcovs = []
+      if accum
+        pcovs = (readlines[cfile] rescue []).map.with_index do |line, idx|
+          if line[/^\s*(?:(#####)|(\d+)|-):\s*\d+:(.*)$/n]
+            cov, line = $1 ? 0 : ($2 ? $2.to_i : nil), $3
+            if !sources[idx] || sources[idx].chomp != line.chomp
+              warn("source file changed, ignoring: `#{ cfile }'")
+              break []
+            end
+            cov
+          else
+            p line
+            warn("coverage file corrupted, ignoring: #{ cfile }")
+            break []
+          end
+        end
+        unless pcovs.empty? || pcovs.size == covs.size
+          warn("coverage file changed, ignoring: `#{ cfile }'")
+          pcovs = []
+        end
+      end
+
+      open(cfile, "w") do |out|
+        covs.zip(sources, pcovs).each_with_index do |(cov, line, pcov), idx|
+          cov += pcov || 0 if cov
+          cov = (cov ? (cov == 0 ? "#####" : cov.to_s) : "-").rjust(9)
+          out.puts("%s:% 5d:%s" % [cov, idx + 1, line])
+        end
+      end
+    end
+  end
+end
diff --git a/sample/build-ruby-coverage b/sample/build-ruby-coverage
new file mode 100644
index 0000000..138fd57
--- /dev/null
+++ b/sample/build-ruby-coverage
@@ -0,0 +1,11 @@
+#!/usr/bin/env ruby
+
+require 'chkbuild'
+
+ChkBuild.num_oldbuilds = 3
+ChkBuild.limit(:data=>1024*1024*300, :as=>1024*1024*300)
+
+rbcoverage = File.expand_path(File.join(File.dirname(__FILE__), "../rbcoverage.rb"))
+ChkBuild::Ruby.def_target('trunk', 'coverage', "ENV:RUNRUBYOPT" => "-r" + rbcoverage, :output_interval_timeout => "60min")
+
+ChkBuild.main
$

start-build-ruby-coverage 作成。

$ sudo -H -u concov cp start-build start-build-ruby-coverage
$ sudo -H -u concov vi start-build-ruby-coverage
(略)
$ diff -u start-build start-build-ruby-coverage
--- start-build	2010-02-20 12:40:01.747336990 +0900
+++ start-build-ruby-coverage	2010-02-20 13:03:40.435893794 +0900
@@ -28,11 +28,14 @@

 #ENV['PATH'] = "/usr/local/bin:#{ENV['PATH']}"

+Dir.chdir(File.dirname(__FILE__))
+$LOAD_PATH.unshift(Dir.pwd)
+
 require 'chkbuild'

 #ChkBuild.rsync_ssh_upload_target("akr@boron.rubyist.net::upload")

-load "sample/build-ruby"
+load "sample/build-ruby-coverage"

 #load "sample/build-gcc-ruby"

$ sudo -H -u concov git commit -m "add start-build-ruby-coverage for concov" start-build-ruby-coverage
Created commit 478dd0c: add start-build-ruby-coverage for concov
 1 files changed, 42 insertions(+), 0 deletions(-)
 create mode 100755 start-build-ruby-coverage
$

別途 ruby 1.9.1 と gem をインストールしておく。 thin は必要に応じてインストール。

$ ruby-1.9.1-p378 -v
ruby 1.9.1p378 (2010-01-10 revision 26273) [x86_64-linux]
$ gem list

*** LOCAL GEMS ***

amalgalite (0.12.0)
arrayfields (4.7.4)
innate (2010.01)
rack (1.1.0)
rake (0.8.7)
ramaze (2010.01)
sequel (3.8.0)
$ gem install thin --no-rdoc --no-ri
Building native extensions.  This could take a while...
Building native extensions.  This could take a while...
Successfully installed eventmachine-0.12.10
Successfully installed daemons-1.0.10
Successfully installed thin-1.2.5
3 gems installed
$ gem list

*** LOCAL GEMS ***

amalgalite (0.12.0)
arrayfields (4.7.4)
daemons (1.0.10)
eventmachine (0.12.10)
innate (2010.01)
rack (1.1.0)
rake (0.8.7)
ramaze (2010.01)
sequel (3.8.0)
thin (1.2.5)
$

concov のインストール。 concov.conf の「database_path: /home/chkbuild/concov-data/」のパスを作成。 bin/concov の shebang 書きかえはなぜかうまくいかない (ruby 1.9.1 へのパスが長すぎるためか、ruby ではなく bash で実行されてしまう) ので、 CONCOV_RUBY を追加して bin/concov はそのままにした。

$ cd /home/concov
$ time sudo -H -u concov git clone git://github.com/mame/concov.git
Initialized empty Git repository in /home/concov/concov/.git/
remote: Counting objects: 138, done.
remote: Compreremote: ssing objects: 100% (104/104), done.
remote: Total 138 (delta 41), reused 104 (delta 26)
Receiving objects: 100% (138/138), 150.37 KiB | 125 KiB/s, done.
Resolving deltas: 100% (41/41), done.

real    0m2.356s
user    0m0.036s
sys     0m0.024s
$ sudo mkdir /home/chkbuild/concov-data
$ sudo chmod 2775 /home/chkbuild/concov-data
$ ls -al /home/chkbuild
合計 0
drwxr-sr-x 5 concov   chkbuild 54 2010-02-20 13:11 .
drwxr-xr-x 5 root     root     50 2010-02-20 12:27 ..
drwxrwsr-x 2 chkbuild chkbuild  6 2010-02-20 12:43 build
drwxrwsr-x 2 root     chkbuild  6 2010-02-20 13:11 concov-data
drwxrwsr-x 2 chkbuild chkbuild  6 2010-02-20 12:43 public_html
$ sudo vi update.rb
$ sudo chmod +x update.rb
$ cat update.rb
#!/usr/bin/ruby

# パスの設定
CHKBUILD_CMD = "/home/concov/chkbuild/start-build-ruby-coverage"
BUILD_DIR = "/home/chkbuild/build/ruby-trunk-coverage/"
CONCOV_CMD = "/home/concov/concov/bin/concov"
CONCOV_CONF_PATH = "/home/concov/concov/concov.conf"
CONCOV_RUBY = "/path/to/.rvm/bin/ruby-1.9.1-p378"

date = ARGV[0] || Time.now.strftime("%Y%m%d")
build_dir = BUILD_DIR + date + "T000000"

# 今日の 0 時 0 分時点の ruby ソースコードを chkbuild する
result = system(CHKBUILD_CMD, "build", "--date", date)
exit 1 unless result

# build ディレクトリで gcov を走らせ、.gcov ファイルを生成する
pwd = File.join(build_dir, "ruby")
open(File.join(pwd, "gcov.log"), "w") do |log|
  $stdout.reopen(log)
  $stderr.reopen(log)
  Dir.chdir(pwd)
  Dir.glob("**/*.gcda") do |path|
    dir, path = path[/\Aenc/] ? [".", path] : File.split(path)
    Dir.chdir(File.join(pwd, dir))
    system("gcov", "-l", "-p", "-o", File.dirname(path), path)
  end
end

# concov に .gcov や .rbcov を回収・データベースに登録させる
system(CONCOV_RUBY, CONCOV_CMD, "-c", CONCOV_CONF_PATH, "register", "-d", date, build_dir)
$

データベースの初期化。

$ cd /home/concov/concov
$ sudo -H -u chkbuild $(which ruby-1.9.1-p378) /home/concov/concov/bin/concov init
$ ls -al /home/chkbuild/concov-data
合計 12
drwxrwsr-x 3 root     chkbuild    40 2010-02-20 13:27 .
drwxr-sr-x 5 concov   chkbuild    54 2010-02-20 13:11 ..
-rw-r--r-- 1 chkbuild chkbuild 12288 2010-02-20 13:27 coverage.db
drwxr-sr-x 4 chkbuild chkbuild    27 2010-02-20 13:27 source.db
$

「build log (chkbuild)」用のシンボリックリンク作成。

$ sudo -H -u concov ln -s /home/chkbuild/public_html/ruby-trunk-coverage /home/concov/concov/public/chkbuild

chkbuild 実行とデータ登録。

$ time sudo -H -u chkbuild /home/concov/update.rb

他の日のデータも登録。

$ time sudo -H -u chkbuild /home/concov/update.rb 20100219

古い方から実行しないといけなかったらしいので、消してやり直し。

$ sudo rm -rf /home/chkbuild/public_html/ruby-trunk-coverage
$ sudo rm -rf /home/chkbuild/build/*
$ sudo rm -r /home/chkbuild/concov-data/*.db
$ cd /home/concov/concov
$ sudo -H -u chkbuild $(which ruby-1.9.1-p378) /home/concov/concov/bin/concov init
$ ruby -rdate -e '(Date.new(2010,1,1)..Date.today).each{|d|puts "/home/concov/update.rb #{d.strftime(%(%Y%m%d))}"}'|time sudo -H -u chkbuild sh -ex

以下実行中。


2010年02月21日(Sun)

concov と mod_proxy

concov を 80 番ポートで見えるようにするために apache2 に mod_proxy の設定をしてみた。

thin は「/home/chkbuild/local/bin/thin -p 7001 -c /home/mame/project/concov/ -R /home/mame/project/concov/config.ru -d -l /home/chkbuil/thin/thin.log -P /home/chkbuild/thin/thin.pid start」のように起動すればいいと教えてもらったので、 runit 経由で起動するため /etc/sv/concov/run に

#!/bin/sh
exec 2>&1
USER=concov
export HOME=/home/$USER
export PATH=/home/nisiyama/.rvm/rubies/ruby-1.9.1-p378/bin:/home/nisiyama/.rvm/gems/ruby-1.9.1-p378/bin:/bin:/usr/local/bin:/usr/bin
export GEM_HOME=/home/nisiyama/.rvm/gems/ruby-1.9.1-p378
cd $HOME/concov
exec chpst -u$USER thin -R config.ru -p 7001 start

のような内容のファイルを用意して「ln -s ../sv/concov /etc/service/concov」のように起動した。

apache2 の方は実行中の chkbuild のログなども見えるように ~chkbuild の設定も含めて以下のような設定を追加した。

単純に / を ProxyPass してしまうと /~chkbuild/ や mod_autoindex でのファイル一覧で使われるアイコンが見えなくなってしまうので ! で止めるようにした。

       <IfModule mod_userdir.c>
               UserDir public_html
               UserDir disabled
               UserDir enabled chkbuild
       </IfModule>
       ProxyPass /~chkbuild/ !
       ProxyPass /icons/ !
       ProxyPass / http://localhost:7001/
       <Proxy http://localhost:7001/*>
               Order deny,allow
               allow from all
       </Proxy>

2010年02月22日(Mon)

concov

今年の初めから実行させてみたら、なぜかタイムアウト待ちでなかなか終わらなくて大変なことになっている。 今月末というか来月頭というかの停電のまでに終わらなかったら、途中で止めないとダメかもしれない。


2010年02月23日(Tue)

CID-Keyed Font

http://d.hatena.ne.jp/pair/20100201/1265024958 のように fontforge で CID-Keyed Font を作成して ghostscript(8.70) で使うと例にあるような PostScript は表示できるのに Ryumin-Light-Roman を指定していると英数字などが表示されなかった。

Roman の CMap ファイルをみてみると ASCII 文字は

1 begincidrange
<20> <7e> 231
endcidrange

となっていて、CID 231 から始まる範囲に対応づけられていた。

定義を http://partners.adobe.com/public/developer/en/font/5078.Adobe-Japan1-6.pdf で確認して、 CID-Keyed Font ファイルをもう一度 fontforge で開いて確認してみると CID 2 から 95 あたりはだいたい埋まっていて 232 から 325 のあたりは全くグリフが入っていなかった。 そこで CID 17 のグリフを CID 247 にコピーしてみると、ちゃんと表示されることが確認できた。


2010年02月24日(Wed)

Plone から静的 HTML に変換

Plone はバージョンアップをしようとすると Zope も絡んでいて難しく (sarge から etch のときに大変だった)、今後もちゃんと管理できる人はいないようなので、他の CMS か何かに移行する予定にして、古いコンテンツは静的 HTML に落としておくことにした。

Plone は URL が独特で例えば /ja と /ja/ と /ja/index_html が同じ内容で、相対リンクは base href で何とかしているようにみえた。 そのため、単純に「 wget -m -D ドメイン http://ドメイン/ 」などでは問題が起きるので、plone-to-html.rb というのを作ってファイルに落とすことにした。

作ってみてわかったのは、CSS や画像も (base href を考慮しながら) たどらないとダメとか、画像などは後ろに /view などが付いていることがあって、単純に画像ファイル名そのままのファイルを作ると、作りたいディレクトリ名と衝突して困ったのでディレクトリの中に index.png のようなファイル名で作るようにしたとか、 Last-modified はつけてくれないらしいとかいうことだった。


2010年02月25日(Thu)

shutdown 予約

2010-02-28 の 24 時から 2010-03-01 の 6 時まで電気設備精密点検整備工事の為の停電があるということで、「echo 'shutdown -h now' | sudo at 23:50 2010-02-28」でサーバの shutdown の予約をした。

後日、予約をしておいたのに、早めに shutdown をしてしまったマシンは停電後の最初の起動のときに at で予約していた shutdown が動いてしまったらしく、2回起動しないとダメという状態になってしまっていた。


2010年02月26日(Fri)

[debian] /etc/cron.d とシンボリックリンク

停電に向けて jaooo.good-day.net を社内サーバから SAKURA Internet の専用サーバに移動したが、後で確認してみると /etc/cron.d に置くファイルはシンボリックリンクではなく実ファイルじゃないとダメだったのか、自動更新が動いていなかった。 lenny だとシンボリックリンクでも動いているので、 etch の cron だとダメなのかもしれない。


2010年02月27日(Sat)

concov

21 日から動かしていた concov の update の実行が終わっていた。 最初の方はタイムアウト待ちになってしまうテストがあったらしく、停電前までに終わるのかどうか心配だったが、大丈夫だったようだ。

$ ruby -rdate -e '(Date.new(2010,1,1)..Date.today).each{|d|puts "/home/concov/update.rb #{d.strftime(%(%Y%m%d))}"}'|time sudo -H -u chkbuild sh -ex
(略)
+ /home/concov/update.rb 20100221
292566.21user 16653.87system 154:19:34elapsed 55%CPU (0avgtext+0avgdata 0maxresident)k
763576inputs+92821992outputs (4356major+1467256619minor)pagefaults 0swaps
$

実行結果は、社内にあったマシンを使ったのでドメインも good-day.net を使って http://concov.good-day.net/ で公開している。 http://dame.dyndns.org:7001/ との一番の違いは amd64 環境という点で、CPU が「AMD Opteron(tm) Processor 144」のマシンを使っている。


2010年02月28日(Sun)

津波

ほぼ一日中津波の情報がテレビに出ていたのかもしれない。 ああいう情報は、もうちょっと元の番組の情報に重なって隠さないようには出来ないものなんだろうか。


copyright © 2001-2013 ZnZ
Key fingerprint = 6E14 2C9C DBD7 874D 8B3C CAA8 9B58 5538 ED7E 1B73