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をどうぞ。


2008年11月03日(Mon)

[ruby] bitclustのrack対応

nginx + webrick でるりまを公開する方法をみて、mod_rack(passenger)を使えばいいのではないかと思って、rack対応をしてみた。

使い方は[ruby-reference-manual:1282]を参照。


2008年11月08日(Sat)

KOF2008:関西オープンソース2008

k-of 2008に行ってきた。 いろんな人に会えたのが非常に良かった。

redmineのサブプロジェクトはどう使えばいいのか、よくわかっていなかったけど、あきぴーさんにきいてみたところ、Rubyと同じようにtrunkやブランチごとにサブプロジェクトを作って、親プロジェクトは全体に関連する環境整備などに使っているということだった。

dRubyの話はいつもの感じでいつの間にか初版が初刷になっていた。


2008年11月11日(Tue)

コンテントネゴシエーション

chkbuildの結果表示でlastのURLでIRCのbotがapplication/x-gzipになってしまってtitleがとれていなかったので調べてみたところ、/etc/apache2/apache2.confに「AddType application/x-gzip .gz .tgz」があるのが原因だとわかったので、VirtualHostの設定の中に

  • RemoveType .gz .tgz
  • AddEncoding x-gzip .gz .tgz

を追加したところ、IRCのbotがtitleをとれるようになった。

[ruby] YAML.load YAML.dump が round trip しない例

Marshal.dump出来ないものはおいといて、単純なStringでもダメなことがあるのがダメっぽい。

YAML.load(YAML.dump("\n a\nb")) # ArgumentError: syntax error on line 3, col 0: `b'
YAML.load(YAML.dump("\n a\n")) #=> "\na\n"

様々な問題の原因は、YAMLの仕様は悪くなくてrubyに標準添付されてるsyckの実装が悪いだけだという噂。


2008年11月12日(Wed)

[ruby] printf

Ruby は %1$c 無いので、」と書いているけど、「printf a="printf a=%1$c%2$s%1$c,34,a",34,a」のように使えるはず。


2008年11月16日(Sun)

[debian] /etc/network/interfacesについて

stanzaとは

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

auto stanzaはifup -aでupするinterfaceの設定。 複数設定したい場合は、1行に複数並べてもいいし、複数回auto stanzaを書いてもいい。

allow-hotplug 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

mapping stanzaはscriptの実行結果によって設定を切り替えたいときに使う。 /usr/share/doc/ifupdown/examples/以下に、ノートPCで差したPCカードのMACアドレスによって設定を変えたり(get-mac-address.sh)、特定のIPアドレスにpingが通るかどうかによって設定を変えたり(ping-places.sh)する例がある。

iface stanza

iface stanzaが、普通のネットワーク設定を書くところ。 「iface 名前 アドレスファミリ メソッド」という行で始まる。

iface stanzaは、普通はeth0などの物理interface名を最初の引数に書くが、代わりに論理名を書いておいて、「ifup ath0=home」のように使うこともできる。 (以前、/etc/network/run/ifstateに「lo=lo」とか「eth0=eth0」のようにあって、何の意味があるんだろうと思っていたが、「ifup ath0=home」とするとifstateに「ath0=home」と書き込まれていて、こういう場合に「=」の左右が違うことがあるということを知った。)

ifaceオプション

アドレスファミリなどに関係なく共通で使えるオプションとして、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/」以下のスクリプトで使っているから。)

inetアドレスファミリ

IPv4のネットワーク設定。

loopbackメソッド
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される前に設定できていいかもしれない。

staticメソッド

addressとnetmaskは必須。 broadcastとnetworkはaddressとnetmaskがあればわかるので、わざわざ書いて間違える可能性を増やす必要はないと思う。 gatewayも設定することが多い。

manualメソッド

up,downなどで全部自前で設定するとき用。 (bondingのslave用NICにNetworkManagerとかが余計なことをしないように「iface eth1 inet manual」だけ書いておくという使い方もしたことがある。)

dhcpメソッド

dhclientなどでdhcpクライアントとしてネットワークの設定をする。 (ifdownのときにも/etc/network/interfacesを見て何をするかが決まっているので、dhcpをstaticに書き換えてから/etc/init.d/networking restartをしてしまうと、dhcpクライアントのプロセスが残ってしまって、いつの間にかIPアドレスが変わって悩む、という失敗が良くある。)

その他

その他のアドレスファミリやメソッドについては省略。

詳しいことはinterfacesのmanとかをみてください。


2008年11月20日(Thu)

Mac mini

Mac miniのHDDがまたエラーで起動しなくなっていた。前はfsckでひっかかって再起動しまくってたけど、今度は画面が灰色(?)一色になって起動しなくなって、インストール用ディスクから起動して修復しようとしてみたらダメだったので、HDDを交換した方がよさそう。

一番の問題はあんなあけにくそうなものをどうすればいいのかというところ。


2008年11月21日(Fri)

[debian] RAMRUN=yes と sudo

「/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.

2008年11月25日(Tue)

ubuntuで「\」の文字化け

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>

[linux] pmountとcodepage

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の情報からつけているわけではなかった。


2008年11月26日(Wed)

[ruby] sqlite3

gemでsqlite3-rubyがちゃんと入っているのに「require 'rubygems'」の後の「require 'sqlite3'」がLoadErrorになるので調べてみたら、merbを入れてみたときに一緒に入ったdo_sqlite3が原因だったので、uninstallしたら「require 'sqlite3'」が通るようになった。


2008年11月27日(Thu)

[ruby] tdiary antirefspam 調査

現象: 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

2008年11月28日(Fri)

[linux] gitkで日本語表示

Ubuntu 8.04のgitkでUTF-8のファイル中の日本語の部分が表示されていなかったので、xfonts-mplusパッケージをインストールしてXにフォントの追加を反映させるためにログインし直して、gitkのメニューのEditのPreferencesからフォントをgoth_pに変更したら日本語も表示できるようになった。


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