最近の更新

関連


その他いろいろ

MODxでつくる! 最強のCMSサイト カバー
MODxでつくる! 最強のCMSサイト

はやくMODx 2.0でないかなあ

リビジョン間の差分やコードの色分け表示に対応したsvnリポジトリのブラウザWebSVN
こんな便利な物があるとは知らず、今までブラウジング目的だけでtrac使っていました。
早速乗り換えるべく設置してみましたが、バージョン2.2.1をUTF-8で使っていると、他の文字コードで化けてファイルの中身が一切表示されなかったりします。

そこでWebSVNの文字化け対策 - okonomiの日記を参考に2.1.1版のパッチを書きました。/usr/bin/nkfを利用しています。

diff -ur websvn-2.2.1/include/svnlook.php websvn/include/svnlook.php
--- websvn-2.2.1/include/svnlook.php    2009-05-10 20:19:20.000000000 +0900
+++ websvn/include/svnlook.php  2009-06-28 09:44:13.000000000 +0900
@@ -558,7 +558,7 @@
     // If there's no filename, we'll just deliver the contents as it is to the user
     if ($filename == "") {
       $path = encodepath($this->getSvnpath($path));
-      passthruCommand($config->svn." cat ".$this->repConfig->svnParams().quote($path.'@'.$rev).' '.$pipe);
+      passthruCommand($config->svn." cat ".$this->repConfig->svnParams().quote($path.'@'.$rev).' '.'|/usr/bin/nkf -w'.$pipe);
       return $highlighted;
     }

@@ -570,7 +570,7 @@
     if ($l == "php") {
       // Output the file to the filename
       $path = encodepath($this->getSvnpath($path));
-      $cmd = $config->svn." cat ".$this->repConfig->svnParams().quote($path.'@'.$rev).' > '.quote($filename);
+      $cmd = $config->svn." cat ".$this->repConfig->svnParams().quote($path.'@'.$rev).'|/usr/bin/nkf -w'.' > '.quote($filename);
       $retcode = 0;
       execCommand($cmd, $retcode);
       if ($retcode != 0) {
@@ -632,6 +632,7 @@

         $path = encodepath($this->getSvnpath($path));
         $cmd = $config->svn." cat ".$this->repConfig->svnParams().quote($path.'@'.$rev).' | '.
+          "/usr/bin/nkf -w |".
           $config->enscript." --language=html ".
           ($l ? "--color --pretty-print=$l" : "")." -o - | ".
           $config->sed." -n ".$config->quote."1,/^<PRE.$/!{/^<\\/PRE.$/,/^<PRE.$/!p;}".$config->quote." > $tempname";
@@ -648,7 +649,7 @@
       } else {
         $highlighted = false;
         $path = encodepath(str_replace(DIRECTORY_SEPARATOR, "/", $this->getSvnpath($path)));
-        $cmd = $config->svn." cat ".$this->repConfig->svnParams().quote($path.'@'.$rev).' > '.quote($filename);
+        $cmd = $config->svn." cat ".$this->repConfig->svnParams().quote($path.'@'.$rev).' |/usr/bin/nkf -w> '.quote($filename);
         $retcode = 0;
         execCommand($cmd, $retcode);
         if ($retcode != 0) {
@@ -727,7 +728,7 @@

     // Output the file to the filename
     $path = encodepath($this->getSvnpath($path));
-    $cmd = $config->svn." cat ".$this->repConfig->svnParams().quote($path.'@'.$rev).' > '.quote($filename);
+    $cmd = $config->svn." cat ".$this->repConfig->svnParams().quote($path.'@'.$rev).'|/usr/bin/nkf -w'.' > '.quote($filename);
     $retcode = 0;
     execCommand($cmd, $retcode);
     if ($retcode != 0) {
@@ -777,7 +778,7 @@

       // Output the file to a temporary file
       $path = encodepath($this->getSvnpath($path));
-      $cmd = $config->svn." cat ".$this->repConfig->svnParams().quote($path.'@'.$rev).' > '.$tmp;
+      $cmd = $config->svn." cat ".$this->repConfig->svnParams().quote($path.'@'.$rev).' | /usr/bin/nkf -w > '.$tmp;
       $retcode = 0;
       execCommand($cmd, $retcode);
       if ($retcode != 0) {
@@ -797,12 +798,13 @@
       if ($config->useEnscript) {
         $path = encodepath($this->getSvnpath($path));
         $cmd = $config->svn." cat ".$this->repConfig->svnParams().quote($path.'@'.$rev).' | '.
+          "/usr/bin/nkf -w|".
           $config->enscript." --language=html ".
           ($l ? "--color --pretty-print=$l" : "")." -o - | ".
           $config->sed." -n ".$config->quote."/^<PRE.$/,/^<\\/PRE.$/p".$config->quote;
       } else {
         $path = encodepath($this->getSvnpath($path));
-        $cmd = $config->svn." cat ".$this->repConfig->svnParams().quote($path.'@'.$rev);
+        $cmd = $config->svn." cat ".$this->repConfig->svnParams().quote($path.'@'.$rev).'|/usr/bin/nkf -w';
         $pre = true;
       }

昨日、zshでsudoや|を無視して履歴から補完する設定を紹介しましたが、
これをC-P/C-Nにしてしまうと、例えば本当にsudo付きだったldconfigを補完する目的で

sudo l(補完)

とすると肝心の物が引っかからず、

sudo ls ..

などと補完されてしまうのが時々鬱陶しいので、Alt-P / Alt-Nに設定してみました。

zle -N smart-search-history-backward
bindkey '^[p' smart-search-history-backward
zle -N smart-search-history-forward
bindkey '^[n' smart-search-history-forward

この辺は好みに応じてC-P/Nの場合はパイプだけ無視して補完、M-P/Nはsudoも含めて無視して補完、などとすると良いかもしれません。

ちょっと嵌ったのが、bindkeyのキーでAlt(Meta)を指定するには\M-pとか^[pとかありますが、これは大文字小文字センシティブらしいこと。Ctrlでは気にする必要無かったので全部大文字にしてたら引っかかりました。

ちなみに^[は本当のC-[ではなく、単にハットと開始カギ括弧です。

現実逃避として格好のシェルスクリプト書き。今回はXのクリップボード操作コマンドであるxselを利用して、stdout (+stderr)をクリップボードにコピーする(更にまたstdoutに書き戻す)zshのグローバルエイリアスを書いてみました。

if exists xsel; then
  alias -g   B=" | xsel -bi" # stdout => clip
  alias -g  B2=" 2>&1 | xsel -bi" # stdout + stderr => clip
  alias -g  BB=" | (cat 1>&2 | xsel -bi) 2>&1" # stdout => clip and stdout
  alias -g BB2=" 2>&1 | (cat 1>&2 | xsel -bi) 2>&1" # stdout, stderr => clip and stdout
fi

zshにおけるグローバルエイリアスとは、alias -gで定義され、「コマンドライン中のどこでも」展開されるエイリアスです。普通のエイリアスは先頭でないと展開されませんが、グローバルエイリアスを用いることで、コマンド末尾につけるパイプ的な処理を効率化することが出来ます。

lessやgrepなどをLとかGとか設定すると便利です。

今回設定したB, B2, BB, BB2ですが、

  • B はstdoutをクリップボードにコピー
  • B2 はstdoutとstderrをクリップボードにコピー
  • BB はstdoutをクリップボードにコピーし、またstdoutに出力
  • BB2 はstdoutとstderrをクリップボードにコピーし、またstdoutに出力

となっています。
名前をC, C2, .. としなかったのは、

make CC=g++

などとしてコマンドライン中で普通に使われそうだったからです。この辺は完全に好みなので何でも良いと思いますが。

早速zshrcに追加したので、まだzshを使っていなくても、丸々コピペですぐに便利設定にできます。

2009 06 13

zshrc拡充

前回zshrcを公開してみました。
あまり最近は弄ってなかったのですが、不思議なもので公開したとたんに弄りたくなってきてしまって、数日でだいぶ変わってしまいました。

今回は以下が主な変更点です。

  • Ctrl-6で直上のディレクトリに移動(バッファはそのまま)
  • バッファ(入力欄)が空の状態でEnterするとls
  • Ctrl-Oで直前のディレクトリに戻る(バッファはそのまま)
  • .profile, .bashrc, .bash_profileなどのPATH設定をインポートする

Ctrl-6で直上移動は.zshrcの設定 - tsakaの日記の設定をそのまま使わせて貰いました。

二番目の「バッファ空でEnter=>ls」は我ながらかなり便利だと思っています。zleの$BUFFERを使うと他にも色々良いことが出来そうです。

2009 06 6

マイzshrc

だいぶ前から、各環境でzshを(半)ログインシェルとして使っています。

中身もあまり変化しないのでここらで公開してみます。
zsh
.zshrc

基本的には割と標準的な設定だと思います。プロンプトはやや情報過多かもしれませんが、ホスト名、ユーザ名、カレントディレクトリ、サスペンドしているジョブ、時刻を2行で表示しています。

TomcatでSubsonicで(多分他のアプリケーションでも)日本語ファイルが扱えない場合の対処方法。

サーバの起動を

$ sudo vim /etc/init.d/tomcat5.5 restart

などとすると、暗黙に環境変数のLANG=ja_JP.UTF-8を引き継いでいたらしく、Tomcatで動くSubsonicで日本語ファイル名が正しく扱えていました。

ところが、マシンごと再起動するとLANG=Cのinitに起動されるためか、日本語文字を1つでも含むファイルは表示されなくなってしまいました。

Tomcat5.5が起動時に読む設定ファイルを編集します。

$ sudo vim /etc/default/tomcat5.5
#これを追加
export LANG=ja_JP.UTF-8

これでLANG=Cの環境でTomcatを再起動したとしても、Subsonic側から日本語文字列を含むファイルを表示・再生できるようになります。

本当は複数のTomcatアプリを走らせる場合に影響が及ばないように、web.xmlを弄ってどうにかしたかったのですが。javaEncodingやfileEncodingかとも思って弄ってみましたが、直せませんでした。良い方法を知っていたら是非教えてください。

先日リリースした、ミュージックストリーミングサーバSubsonicの日本語化ですが、自分で使っているうちにいくつか誤りに気づいたので、修正版(20090416版)を公開します。

言語ファイルのみは
Subsonic-ResourceBundle_ja_JP-20090416.zipから。

パッケージされたwarファイルは
subsonic-ja-20090416.warから。

導入方法は昨日のエントリを参照してください。

ミュージックストリーミングサーバ、Subsonicの日本語言語ファイルを書いてみました。

SubsonicはJava (JSPサーブレット) で書かれ、フォルダ管理を基本としたマルチプラットフォームで動作するGPLのストリーミングサーバです。
配信方法はブラウザ上のFlashプレーヤ、外部プレーヤ(直接ストリーミング)、外部プレーヤ+プレイリストの3種類を選べます。
帯域制限をかけて、lameでリアルタイムにビットレートを落として再エンコードしながら配信することもできます。
それからPodcastの巡回もできるらしい。あまり使ってないからよく分からないけど。

なかなか便利でよさそうですが、日本語化されていなかったようなので書いてみました。
まあ曲名などは元々日本語で通るので、べつに英語でも使用に支障はないんですが…

インストールするとこのような感じになります。
Subsonic日本語化

導入は、Subsonic-ResourceBundle_ja_JP.zipをダウンロードし、展開します。この中のResourceBundle_ja_JP.propertiesが言語設定ファイル。

subsonic.warを展開したWEB-INF/classes/net/sourceforge/subsonic/i18nの中にコピーし、
同じディレクトリにあるlocales.txtの末尾に

# Janapese
ja_JP

と追記します。

あとはTomcatを再起動すれば、個人設定画面から日本語が選べるようになります。誤訳などあれば連絡してください。

(一応本家にも送ってみました、採用されるのか分かりませんが)

追記。上記の操作を済ませて再パッケージしたwarファイルを公開します。subsonic.war
これを元々のsubsonic.warに上書きすれば、日本語が選択できるようになります。

さらに追記。いくつかの誤りを修正したバージョンを公開しました。

sshするたびに秘密鍵のパスフレーズを入力しなければならないのも、事前にssh-agentを起動し、忘れずにssh-addするのも面倒だ!という人向けのスクリプト、lazy-ssh-agentを書いてみました。

シェル起動後最初にssh/scp/sftpする時にパスフレーズを要求し、それ以降はssh-agentが鍵を保持します。

sshする用もないのに.bashrc等にeval `ssh-agent` && ssh-addを書いておくという煩わしさからの解放。

ここ最近メールサーバを立てて色々弄っています。

今は中規模の組織のスパムメールのフィルタリングについて検討中。
クライアント側に負荷の少ない方法というのが中々難しい。

複数箇所からのPOPに加えてIMAPも想定すると、配送の段階でのフォルダ分けは非現実的なので、タグ付け=>振り分けは(希望者は)クライアントで、という構成になりそうです。

bogofilterは過去のスパム/非スパム判定をもとに新着メールを判定しますが、まずそんな物は取っておいてないため、実験にも非常に苦労する。

nkf|mecab||nkf|bogofilter|reformail -X とすると、本文に比べてヘッダの割合が結構大きく、そっちを無駄に学習してしまって学習初期の結果かなり不安定です。
(nkf 2回通してるのは完全に無駄で、mecab辞書をjisで作れば良いだけですが…)

間違って判定されたメールをどうやって正しく教え込むか、というのもサーバサイドでフィルタを動かす上では難しい話です。

  • クライアント側で適当にフォルダ分けしたmboxを適宜アップロード
  • メール返信・転送を利用

あたりが思いつくところですが、前者はエクスポート・mboxの転送、「過去に学習した分」を排除して再学習、と面倒な上に記憶容量をかなり無駄遣いしそう。

ということで、数が多くなると面倒ですが、1、2通なら手軽に出来る後者を採用してみました。
testuser@example.comに間違ってスパムと判定された非スパムメールが届いた場合、
testuser-ham@example.comに転送すると、それを「スパム取り消し非スパム学習(-Sn)」でbogofilterに掛け、配送せずに破棄します。

maildropの設定ファイル、.mailfilterは以下のように。(抜粋)

if (/^To: *.*-spam@/:h)
{
        log "Ham to Spam"
        `${NKF} -mJe | ${WAKATI} | ${NKF} -Ej | ${BOGOFILTER} -Ns`
        exit
}
if (/^To: *.*-ham@/:h)
{
        log "Spam to Ham"
        `${NKF} -mJe | ${WAKATI} | ${NKF} -Ej | ${BOGOFILTER} -Sn`
        exit
}

こんな感じ。

スパム度の上昇

確かにspamisityが上昇しています。実際に運用する際は、1通ずつしか対応できないのは都合が悪いので、先のmboxの取り込みと併用することになると思いますが。

まだこれは1ユーザ単位でやっていますが、複数ユーザのフィルタの統合を取り入れるとまた面倒そう…

« 前のページ次のページ »