リンクするaprのバージョンを0.9xから1.2xに
WebDAV(=Apache)でリポジトリにアクセスすると、500が返ってきてログにも何も残らないと言う現象に遭遇する。で、色々調べていくうちのSubversionとApacheのaprのバージョンの不整合が原因と言う事が分かった。
なお、Apache HTTP Server 2.0系で利用されているAPR 0.9系と、Apache HTTP Server 2.2系で利用されているAPR 1.2系では、互換性がないことに注意されたい。
http://builder.japan.zdnet.com/news/story/0,3800079086,20361867,00.htm
トラブルシューティングの手順を残しておく。
まず、Apacheのログに何も残っていないので、telnetから直接WebDAVのリクエストを投げる。参考:Subversionによるバージョン管理 (2/3):Apache 2.0でWebDAV(後編) - @IT
$ telnet localhost 80 OPTIONS /svn/ HTTP/1.1 Host: hostname Authorization: Basic ===============
すると、xmlでエラーの詳細が返ってくる。
HTTP/1.1 500 Internal Server Error Date: Fri, 08 Feb 2008 02:43:28 GMT Server: Apache Content-Length: 290 Connection: close Content-Type: text/xml; charset="utf-8" <?xml version="1.0" encoding="utf-8"?> <D:error xmlns:D="DAV:" xmlns:m="http://apache.org/dav/xmlns" xmlns:C="svn:"> <C:error/> <m:human-readable errcode="22"> Can't set position pointer in file '/path/to/repos/db/revs/2406': Invalid argument </m:human-readable> </D:error> Connection closed by foreign host.
ポイントは以下。
Can't set position pointer in file '/path/to/repos/db/revs/2406': Invalid argument
これでググる。http://saikyoline.jp/wiki/index.php?%A5%E1%A5%E2%2FWebDAV%A4%C7Subversionでaprのバージョンが原因と書いてある。
Subversionはそのままだと同梱のAPR(0.9.7)を使ってしまうので、Apache 2.2.0に同梱のAPR(1.0)を使わせるため「--with-apr」と「--with-apr-util」を指定する。
指定しなくてもコンパイルもできてApacheもしっかり起動するが、アクセスするときにCan't set position pointer in file '/var/lib/svn-repos/db/revs/0': Invalid argument
http://saikyoline.jp/wiki/index.php?%A5%E1%A5%E2%2FWebDAV%A4%C7Subversion
みたいなこと言われてハマる
aprのバージョンを確認するにはlddを使う。まずはSubversion(mod_dav_svn)。
$ ldd /usr/local/apache2/modules/mod_dav_svn.so libaprutil-0.so.0 => /usr/lib/libaprutil-0.so.0 (0x008f9000) libapr-0.so.0 => /usr/lib/libapr-0.so.0 (0x00270000) (snip) $ ll /usr/lib/libapr*.0 lrwxrwxrwx 1 root root 18 1月 25 14:57 /usr/lib/libapr-0.so.0 -> libapr-0.so.0.9.17 lrwxrwxrwx 1 root root 22 1月 25 14:57 /usr/lib/libaprutil-0.so.0 -> libaprutil-0.so.0.9.17
恐らく0.9.17。次にApache。
$ ldd /usr/local/apache2/bin/httpd libaprutil-1.so.0 => /usr/local/apache228/lib/libaprutil-1.so.0 (0x0078a000) libapr-1.so.0 => /usr/local/apache228/lib/libapr-1.so.0 (0x00b5d000) $ ll /usr/local/apache228/lib/libapr*.0 lrwxrwxrwx 1 root root 18 2月 6 16:03 /usr/local/apache228/lib/libapr-1.so.0 -> libapr-1.so.0.2.12 lrwxrwxrwx 1 root root 22 2月 6 16:03 /usr/local/apache228/lib/libaprutil-1.so.0 -> libaprutil-1.so.0.2.12
恐らく1.2.12。確かにバージョンが違う。
と言うわけで、再々度Subversionをコンパイル。この際なので色々オプションを調べて自分なりのconfigureを作る事に。
./configure \ --with-apr=/usr/local/apache2 \ --with-apr-util=/usr/local/apache2 \ --with-apxs=/usr/local/apache2/bin/apxs \ --with-swig=/usr/local/bin/swig \ --with-neon=/usr/local/ \ PERL=/usr/local/bin/perl \ PYTHON=/usr/local/bin/python \ RUBY=/usr/local/bin/ruby \ --with-ssl \ --without-berkeley-db
これでインストールしたらWebDAVで無事アクセスできた。いい加減これで全部かなー。
sudoのちょっとしたトラブル
root以外のユーザを指定してsudoを実行しようとすると、実行を許可されていません、みたいなエラーが出た。
$ sudo -u foo ls / Sorry, user hoge is not allowed to execute '/bin/ls /' as foo on host_name.
色々調べていると、sudoersファイル内でユーザ権限の設定をしていない事が分かった。
hoge ALL = (ALL) [NOPASSWD:] ALL #一つ目のALLは接続元、二つ目の括弧付きALLはユーザ、三つ目はコマンドをそれぞれ表している。
二つ目の括弧付きを省略していると、ユーザはrootのみになる。sudo -lで自分の設定を確認できる。
$ sudo -l User hoge may run the following commands on this host: (root) NOPASSWD: ALL
sudoersファイルの修正後。
$ sudo -l User hoge may run the following commands on this host: (ALL) NOPASSWD: ALL
よく分からないまま使っているとトラブル発生時に困る例。
mongrel_clusterは複数バージョンが混合していると古いバージョンが使われる
開発環境にmongrel_clusterの1.0.5を入れてソースを眺めていたら、cluster::statusと言う新しいコマンドが増えていたのだけれど、リストに出てこなかったので、0.2.1をアンインストールしたら出てきた。
この辺りはgem_pluginの仕様なんだと思うけど、仕組みが謎。
全角スペース対応版strip
書いてみた。
速度的にはまだまだ改善の余地があると思う。
class String def strip_with_full_size_space s = " \s\v" self =~ /^[#{s}]+([^#{s}]+)[#{s}]+$/ ? $1 : self end end
ベンチマーク用のコード。
require 'benchmark' n = 50000 s1 = " 全半混在 " Benchmark.bm do |x| x.report("s1") { n.times do s1.strip_with_full_size_space end } x.report("s1") { n.times do s1.strip end } end
結果。
user system total real s1 0.130000 0.000000 0.130000 ( 0.122258) s1 0.020000 0.000000 0.020000 ( 0.027868)
正規表現のoオプションを外したバージョンの結果。
user system total real s1 0.740000 0.010000 0.750000 ( 0.739665) s1 0.020000 0.000000 0.020000 ( 0.027248)
oオプションの有無で5〜6倍近く実行速度に差が出る。
irbの起動時はLoadErrorが発生しても無視されるが、その後のライブラリの読み込み等は行われない
.irbrcで
require 'hogehoge'
とやっても例外も警告も出なかったので、なんでだろうと思って調べてみた。
irbの起動処理はirb/init.rb内で行われる。このうち、irbrcを読み込んでいるのはIRB.run_configメソッドだと思われる。以下にコードを抜粋する。
def IRB.run_config if @CONF[:RC] begin load rc_file rescue LoadError, Errno::ENOENT rescue print "load error: #{rc_file}\n" print $!.class, ": ", $!, "\n" for err in $@[0, $@.size - 2] print "\t", err, "\n" end end end end
コードを見ると、.irbrcをrubyファイルとみなしてloadしている。つまり、途中で例外が発生した場合には以降の処理(require)は行われず、またそれを警告するメッセージ等も出力されない事になる。これはハマりそうだ…。
オーバーライドして置き換えてもいいのだけれど、まぁそんな事あまりないだろうから放置する事にする(と、皆考えるからずっと放置されている気がする)。
Subversionでhttp(s)のURLスキームを認識しない問題を解決する。
RetrospectivaのtrunkをGoogle Codeからcoしようとしたらエラーが出る。
$ svn co -q http://retrospectiva.googlecode.com/svn/trunk/ retrospectiva svn: 'http://retrospectiva.googlecode.com/svn/trunk' 用の URL スキームを認識できません
色々調べてみたものの分からなかったので、エラーメッセージでググるとあっさり原因が見つかった。svnコマンドでhttp(s)系のリポジトリにアクセスする場合には、neonと言うライブラリが必要になるらしい。subversionのINSTALLファイルには以下のように書かれている。
4. Neon library 0.25.x or 0.26.x (http://www.webdav.org/neon/) The Neon library allows a Subversion client to interact with remote repositories over the Internet via a WebDAV based protocol. If you want to use Subversion to connect to a server over ra_dav (via a http:// or https:// url), you will require Neon. (See also section I.11 for information about "serf", an experimental alternative to Neon for accessing servers over WebDAV.)
まず既存環境にNeonがあるか確認する。
$ rpm -qa | grep -i neon neon-0.24.7-4
あった。でも要件を満たしていないようだ。と言うわけでNeonを含めてSubversionを再コンパイルする。NeonはNeon公式からダウンロードするか、Subversionの依存ファイルを一括してパッケージしたtarファイルに含まれている。今回は後者を利用する。インストール方法も同様にINSTALLファイルに書かれているのでこれを参考に。
The source code is included with the Subversion dependencies package, and it can also be obtained from: http://www.webdav.org/neon/neon-0.25.5.tar.gz -or- http://www.webdav.org/neon/neon-0.26.1.tar.gz Building Neon inside the subversion build: The Neon library source code can be placed in "./neon" if you want Subversion to build it as part of the Subversion build process. Unpack the archive using tar/gunzip. Rename the resulting directory from ./neon-0.XX.Y to just "./neon", inside the top level of your Subversion source tree. (This is what unpacking the Subversion dependencies package does, too.)
手順は以下の通り。
$ wget http://subversion.tigris.org/downloads/subversion-1.4.6.tar.gz $ tar zxf subversion-1.4.6.tar.gz $ wget http://subversion.tigris.org/downloads/subversion-deps-1.4.6.tar.gz $ tar zxf subversion-deps-1.4.6.tar.gz $ cd subversion-1.4.6 $ ./configure $ make $ sudo make install
特に問題なく終了。configure時には以下の出力を確認した。
# #configure: Configured to build neon 0.25.5: # # Install prefix: /usr/local # Compiler: gcc # XML Parser: expat # SSL library: SSL support is not enabled # zlib support: zlib support enabled, using -lz # Build libraries: Shared=no, Static=yes
再度チェックアウトし、無事チェックアウト出来る事を確認。
2008/1/29 追記
上記の手順でコンパイルした後、svkが動作しなくなったり、rubyのSubversionバインディングが動かなくなったりした。バインディングはバージョンが古いだけだったのだけれど、svkは原因がよく分からなかった。
以前とconfigureのオプションが違っていたりする事はあったのだが、Subvresionの依存パッケージにはNeon以外にapr,apr-util,zlibが入っていたので、それが問題になったのかもしれない。復旧した際にはNeon単体のみをソースツリーに含めるようにした。
2008/1/29 追記 その2
configureに--with-sslオプションを追加しないとhttpsでチェックアウトが出来なかったので、再度コンパイルし直し。
$ ./configure \ PERL=/usr/local/bin/perl \ PYTHON=/usr/local/bin/python \ --with-swig=/usr/local/bin/swig \ --with-ssl $ make $ sudo make install
コンパイル前。
$ svn --version (snip) 以下のリポジトリアクセス (RA) モジュールが利用できます: * ra_dav : WebDAV (DeltaV) プロトコルを使ってリポジトリにアクセスするモジュール。 - 'http' スキームを操作します * ra_svn : svn ネットワークプロトコルを使ってリポジトリにアクセスするモジュール。 - 'svn' スキームを操作します * ra_local : ローカルディスク上のリポジトリにアクセスするモジュール。 - 'file' スキームを操作します
コンパイル後。
$ svn --version (snip) 以下のリポジトリアクセス (RA) モジュールが利用できます: * ra_dav : WebDAV (DeltaV) プロトコルを使ってリポジトリにアクセスするモジュール。 - 'http' スキームを操作します - 'https' スキームを操作します * ra_svn : svn ネットワークプロトコルを使ってリポジトリにアクセスするモジュール。 - 'svn' スキームを操作します * ra_local : ローカルディスク上のリポジトリにアクセスするモジュール。 - 'file' スキームを操作します