Cygwin で、procmail + bogofilter が固まる
(Cygwin on Windows)

原因と対策について紹介しています。

  1. まえがき
  2. 現象
  3. 対策
  4. 効果

関連するページはこちら、

メール関係全体はこちら

MacOSX & Cygwin on Windows のソフトの事

Emacs 関係はこちら


1. まえがき

Cygwin 上で、例えば、

ls -v ~/Mail/inbox.im/* | sed 's/.*/echo & \; cat & \| procmail -p -m ~\/.procmailrc/g' | /usr/bin/zsh

みたいな、シェルスクリプトで、大量のメールの振り分けを、procmail でしようとすると、固まります。


2. 現象

2.1. 何が起きている?

幾つか問題が有って

俄には信じ難いので、試しに、次の様なスクリプトを、~/bin/processtest.sh として保存して置いて、

#!/usr/bin/zsh

declare -i count=0
declare -i ptest

ptest=`ps -s | egrep -c '(bogofilter)|(gawk)'`

while [ $ptest -gt 0 ];
do
    ptest=`ps -s | egrep -c '(bogofilter)|(gawk)'`
    count=$count+1
done

echo "$count"

.procmailrc から、呼び出して見ました。

# --------------------------------------
# bogofilter の、spamicity を、ヘッダ X-bogosity として挿入
# --------------------------------------
## bogofilter で、spamicity を計算し、SPAMISITY に代入
SPAMICITY=`ruby $HOMEDIR/bin/prepare.rb | bogofilter -t --unicode=no -k 10 | gawk '{print $2}'`

BOGO_PROCESS=`zsh $HOMEDIR/bin/processtest.sh`

これを、前書きで示したスクリプトを使って、1000通位まとめて処理してみました。で、procmail のログファイルを確認してみると、殆んど、BOGO_PROCESS=0 なんですが、ほんの少し、2、3 に成っているのが有ります。

本来、SPAMCITY= のプロセスは、子プロセスが全て終了しなければ、先に進んではいけない筈なのに、gawk の出力を貰うとすぐ次ぎに進んでいる場合が有るようです。

つまり、BOGO_PROCESS= のプロセスが無ければ、procmail は、配送を済ませてさっさと終了することも有り得る訳です。


3. 対策

3.1. nkf

最後の fclose(stdout) の前に、fflush(stdout) を挿入。本来、fclose() は、バッファーをフラッシュしてからクローズする筈なんだけど、Cygwin の fclose() は、EOL をうまく認識できないと、フラッシュしないみたい。—> nkf

3.2. kakasi

取り敢えず、mecab を使う。—> prepare-mecab.rb

3.3. procmail

先ず、スクリプトに、sh 以外を使う。経験上大差あり。

更に、先程の、~/bin/processtest.sh のループに、sleep を入れて、取り敢えず、procmail を停める。

#!/usr/bin/zsh

declare -i count=0
declare -i ptest

ptest=`ps -s | egrep -c '(bogofilter)|(gawk)'`

while [ $ptest -gt 0 ];
do
    sleep 1.0
    ptest=`ps -s | egrep -c '(bogofilter)|(gawk)'`
    count=$count+1
done

echo "$count"

procmail を、停めてる間に、bogofilter や、gawk のプロセスが終了しない場合、強制停止させるように、TIMEOUT を設定。

# --------------------------------------
# bogofilter の、spamicity を、ヘッダ X-bogosity として挿入
# --------------------------------------
## bogofilter で、spamicity を計算し、SPAMISITY に代入
TIMEOUT=90  ## default は、960 (sec.)

SPAMICITY=`ruby $HOMEDIR/bin/prepare-mecab.rb | bogofilter -t --unicode=no -k 10 | gawk '{print $2}'`

BOGO_PROCESS=`zsh $HOMEDIR/bin/processtest.sh`


4. 効果

現在確認中