この日記にはツッコミを入れられます。 ツッコミを入れたい日付をクリックすると、フォームが現れます。
xreaでtDiaryを使う方法はxrea.com で tDiary を使う方法やインストールメモやXREA + tDiary + Namazuをどうぞ。
nginx + webrick でるりまを公開する方法をみて、mod_rack(passenger)を使えばいいのではないかと思って、rack対応をしてみた。
使い方は[ruby-reference-manual:1282]を参照。
k-of 2008に行ってきた。 いろんな人に会えたのが非常に良かった。
redmineのサブプロジェクトはどう使えばいいのか、よくわかっていなかったけど、あきぴーさんにきいてみたところ、Rubyと同じようにtrunkやブランチごとにサブプロジェクトを作って、親プロジェクトは全体に関連する環境整備などに使っているということだった。
dRubyの話はいつもの感じでいつの間にか初版が初刷になっていた。
chkbuildの結果表示でlastのURLでIRCのbotがapplication/x-gzipになってしまってtitleがとれていなかったので調べてみたところ、/etc/apache2/apache2.confに「AddType application/x-gzip .gz .tgz」があるのが原因だとわかったので、VirtualHostの設定の中に
を追加したところ、IRCのbotがtitleをとれるようになった。
「Ruby は %1$c 無いので、」と書いているけど、「printf a="printf a=%1$c%2$s%1$c,34,a",34,a」のように使えるはず。
interfacesファイルはstanzaと呼ばれる固まりを並べるようになっている。
stanzaとは、"iface", "mapping", "auto" や "allow-" で始まる行から始まっている。
auto lo eth0
allow-hotplug eth1
iface lo inet loopback
のようなstanzaならそれぞれ1行だけだし、
mapping eth0
script /usr/local/sbin/map-scheme
map HOME eth0-home
map WORK eth0-work
iface eth0-home inet static
address 192.168.1.1
netmask 255.255.255.0
up flush-mail
のようなstanzaなら複数行で1つのstanzaになっている。 (インデントはあってもなくてもいい)
「#」から始まる行はコメント。 設定の中に「#」を含めることがあるので、設定の行末にはコメントをつけられないと思っておく方が無難。
auto stanzaはifup -aでupするinterfaceの設定。 複数設定したい場合は、1行に複数並べてもいいし、複数回auto stanzaを書いてもいい。
allow-hotplug stanzaは「ifup --allow=hotplug eth0 eth1」のように実行されたときにupするinterfaceの設定。
etchやlennyでは/etc/udev/rule.dの中に
SUBSYSTEM=="net", RUN+="net.agent"
という設定があって、/lib/udev/net.agent経由で「ifup --allow=hotplug」などが実行されている。
mapping stanzaはscriptの実行結果によって設定を切り替えたいときに使う。 /usr/share/doc/ifupdown/examples/以下に、ノートPCで差したPCカードのMACアドレスによって設定を変えたり(get-mac-address.sh)、特定のIPアドレスにpingが通るかどうかによって設定を変えたり(ping-places.sh)する例がある。
iface stanzaが、普通のネットワーク設定を書くところ。 「iface 名前 アドレスファミリ メソッド」という行で始まる。
iface stanzaは、普通はeth0などの物理interface名を最初の引数に書くが、代わりに論理名を書いておいて、「ifup ath0=home」のように使うこともできる。 (以前、/etc/network/run/ifstateに「lo=lo」とか「eth0=eth0」のようにあって、何の意味があるんだろうと思っていたが、「ifup ath0=home」とするとifstateに「ath0=home」と書き込まれていて、こういう場合に「=」の左右が違うことがあるということを知った。)
アドレスファミリなどに関係なく共通で使えるオプションとして、pre-up,up(post-up),down(pre-down),post-downの4種類がある。 /etc/network/if-*.d/ に置かれたスクリプトも同じタイミングでrun-partsで実行される(つまり/etc/cron*ly以下などと同じく「.」などが含まれていると実行されない)。
スクリプトにはiface stanzaの情報として環境変数IFACE,LOGICAL,ADDRFAM,METHOD,MODE,PHASE,VERBOSITYが渡される。 他のオプションは「IF_」で始まる環境変数で渡される。 (wireless-toolsパッケージを入れたら「wireless-」で始まるオプションが使えたり、wpasupplicantパッケージを入れたら「wpa-」で始まるオプションを使えたり、resolvconfパッケージを入れたら「dns-」で始まるオプションが使えたり、ifenslave-2.6パッケージを入れたら「slaves」オプションが使えたりするのは、この「IF_」で始まる環境変数を「/etc/network/if-*.d/」以下のスクリプトで使っているから。)
IPv4のネットワーク設定。
iface lo inet loopback
のこと。
iptablesの設定にiptables-restoreを使っているのなら、
# The loopback network interface auto lo iface lo inet loopback pre-up /sbin/iptables-restore < /etc/network/iptables.txt
のようにloのpre-upに設定しておけば他のinterfaceがupされる前に設定できていいかもしれない。
addressとnetmaskは必須。 broadcastとnetworkはaddressとnetmaskがあればわかるので、わざわざ書いて間違える可能性を増やす必要はないと思う。 gatewayも設定することが多い。
up,downなどで全部自前で設定するとき用。 (bondingのslave用NICにNetworkManagerとかが余計なことをしないように「iface eth1 inet manual」だけ書いておくという使い方もしたことがある。)
dhclientなどでdhcpクライアントとしてネットワークの設定をする。 (ifdownのときにも/etc/network/interfacesを見て何をするかが決まっているので、dhcpをstaticに書き換えてから/etc/init.d/networking restartをしてしまうと、dhcpクライアントのプロセスが残ってしまって、いつの間にかIPアドレスが変わって悩む、という失敗が良くある。)
その他のアドレスファミリやメソッドについては省略。
詳しいことはinterfacesのmanとかをみてください。
Mac miniのHDDがまたエラーで起動しなくなっていた。前はfsckでひっかかって再起動しまくってたけど、今度は画面が灰色(?)一色になって起動しなくなって、インストール用ディスクから起動して修復しようとしてみたらダメだったので、HDDを交換した方がよさそう。
一番の問題はあんなあけにくそうなものをどうすればいいのかというところ。
「/etc/default/rcS」で「RAMRUN=yes」にすると、sudoで再起動後にいつもlecture(以下のようなもの)が出てくるようになってしまうので、visudoで「Defaults !lecture」と設定した。
We trust you have received the usual lecture from the local System
Administrator. It usually boils down to these three things:
#1) Respect the privacy of others.
#2) Think before you type.
#3) With great power comes great responsibility.
ubuntuでbackslashがyen signに文字化けするのが非常に気持ち悪いので、gnome-terminalはVL Gothicを設定していたが、Firefoxでも化けてしまっていたので「~/.fonts.conf」を以下の設定に変更した。
<?xml version="1.0"?>
<!DOCTYPE fontconfig SYSTEM "/etc/fonts/fonts.dtd">
<fontconfig>
<match>
<test name="family">
<string>sans-serif</string>
</test>
<edit name="family" mode="prepend" binding="strong">
<string>VL PGothic</string>
</edit>
</match>
<match>
<test name="family">
<string>serif</string>
</test>
<edit name="family" mode="prepend" binding="strong">
<string>Sazanami Mincho</string>
</edit>
</match>
<match>
<test name="family">
<string>monospace</string>
</test>
<edit name="family" mode="prepend" binding="strong">
<string>VL Gothic</string>
</edit>
</match>
</fontconfig>
http://itpro.nikkeibp.co.jp/article/COLUMN/20070611/274354/ や http://d.hatena.ne.jp/kyhrhr/20041207 を参考にして、vfat.fdiを作っていたが、Ubuntu 8.04などで(pamusbなどが内部で使っている)pmountでマウントしたときにcodepageがつかなかったので調べてみた。
ソースまでみた結論としては、pmountはhalのmount_optionはほとんどみていなくて、pmountコマンドのオプションでもcodepageには対応していない。 iocharsetはUTF-8 localeの時に自動でついているだけで、halの情報からつけているわけではなかった。
現象: antirefspamでNGワードを設定してNGワードにひっかかるとindex.rbのプロセスがなぜか止まってしまっていて、応答が返ってこない。 (2008-11-29追記: Debianパッケージで入れたtdiaryで、tdiaryパッケージのバージョンは2.0.2+20060303-5。2.2系列ではデッドロックはしなくなっているみたい。)
調査: まず止まっている状態のプロセスがどこで止まっているのか調べるために「strace -p $thepid」してみると、LOCK_EXで止まっていることがわかった。 次に「ls -l /proc/$thepid/fd」でどのファイルを開いているのか調べてみると、200811.td2が4と5で開かていて、これがデッドロックしていそうだと気付いた。 次にどこでLOCK_EXを使っているのか調べるために/usr/share/tdiaryをLOCK_EXでgrepしてみると、
$ grep -r LOCK_EX . ./tdiary.rb: f.flock(File::LOCK_EX) ./tdiary/defaultio.rb: fh.flock( File::LOCK_EX ) ./contrib/io/dbi_io/dbi_io.rb: file.flock(File::LOCK_EX) ./contrib/style/hatena/hatena_style.rb: break unless fp.flock(IO::LOCK_EX|IO::LOCK_NB) ./contrib/plugin/select_theme/select_theme.rb: i.flock(File::LOCK_EX) ./contrib/plugin/select_theme/select_theme.rb: o.flock(File::LOCK_EX) ./contrib/util/tdiarysearch/search.rb: f.flock(File::LOCK_EX) $
とでた。contribは関係なさそうなので、まずtdiary.rbをみてみるとキャッシュファイルだったので今回は無関係だった。 次にtdiary/defaultio.rbを見てみると、これが該当する場所だとわかった。
stderrがapacheのerror.logに繋がっていることは/proc/$thepid/fdを見たときに気付いていたので、調査のために「fh.flock( File::LOCK_EX )」の前に「STDERR.puts "tdiary/defaultio.rb:" + caller.inspect」を追加した。 すると以下のログが出てきた。(見易くするために整形済)
tdiary/defaultio.rb:[ "/usr/share/tdiary/tdiary.rb:1559:in `load'", "/usr/share/tdiary/tdiary.rb:1501:in `initialize'", "/usr/share/tdiary/tdiary.rb:1547:in `initialize'", "/usr/share/tdiary/index.rb:31:in `new'", "/usr/share/tdiary/index.rb:31", "index.rb:2:in `require'", "index.rb:2"] tdiary/defaultio.rb:[ "/usr/share/tdiary/tdiary.rb:1661:in `initialize'", "/usr/share/tdiary/index.rb:50:in `new'", "/usr/share/tdiary/index.rb:50", "index.rb:2:in `require'", "index.rb:2"]
tdiary.rbとindex.rbをみても特にあやしいところは見付けられなかったので、更に調査のため、flockの後やyieldやcloseの前後にも出力を追加した。 その結果、yieldから返ってきていないのに次のflockが呼ばれていることがわかった。
これはどこかで例外が発生しているのに握り潰されているのが原因と思い、適当な場所(今回はtdiary/defaultio.rbをいじってしまっていたのでその頭)に「$DEBUG=true」を追加して、例外の発生状況を調べることにした。 すると
Exception `ArgumentError' at /usr/share/tdiary/tdiary/filter/antirefspam.rb:241 - wrong number of arguments (1 for 2) Exception `TDiary::TDiaryError' at /usr/share/tdiary/tdiary.rb:1503 - bad date
という例外が発生していたことがわかった。
原因: antirefspam.rbでlog_spamcommentの引数の数があっていなくて、ArgumentErrorが発生したのをtdiary.rbがTDiary::TDiaryErrorに置き換えていて、それをindex.rbが無視していた。 さらにそのときにflockしたファイルを閉じていなかった。
解決方法: filter/antirefspam.rbを以下のように修正する。
--- antirefspam/filter/antirefspam.rb.orig 2005-08-01 15:55:38.000000000 +0900
+++ antirefspam/filter/antirefspam.rb 2008-11-27 15:02:29.004559668 +0900
@@ -227,7 +227,7 @@
maxsize = @conf['antirefspam.comment_maxsize'].to_i
if maxsize > 0
unless comment.body.size <= maxsize
- log_spamcomment( comment )
+ log_spamcomment( diary, comment )
return false
end
end
@@ -238,14 +238,14 @@
ngwords.to_s.each_line do |ngword|
ngword.sub!(/\r?\n/,'')
if comment.body.downcase.include? ngword.downcase
- log_spamcomment( comment )
+ log_spamcomment( diary, comment )
return false
end
# 含まれなかった場合は "NGワード" を正規表現とみなして再チェック
begin
if comment.body =~ Regexp.new( ngword, Regexp::MULTILINE )
- log_spamcomment( comment )
+ log_spamcomment( diary, comment )
return false
end
rescue
別の解決方法: tdiary/defaultio.rbを以下のように修正して、yieldの中で例外が発生してもちゃんとファイルを閉じるようにする。(以下の差分ではdiffを最小限にするためにインデントは修正していません。)
--- tdiary/defaultio.rb.orig 2006-11-26 13:36:05.000000000 +0900 +++ tdiary/defaultio.rb 2008-11-27 15:17:04.356547695 +0900 @@ -124,11 +124,7 @@ rfile = referer_file( @data_path, date ) begin Dir::mkdir( dir ) unless FileTest::directory?( dir ) - begin - fh = File::open( @dfile, 'r+' ) - rescue - fh = File::open( @dfile, 'w+' ) - end + File::open( @dfile, File::RDWR|File::CREAT ) do |fh| fh.flock( File::LOCK_EX ) cache = @tdiary.restore_parser_cache( date, 'defaultio' ) @@ -147,7 +143,7 @@ @tdiary.store_parser_cache( date, 'defaultio', diaries ) end - fh.close + end if diaries.empty? File::delete( @dfile ) # also delete parser cache