[PREVIOUS CHAPTER] [______TOC_______]
2 まとめおくり


2.1	まとめおくりの基本原理

"まとめおくりのプロセス"は一定時間ごとに起動しその間に来た記事をまとめ
て配送します。

   for (;;) {	# 無限ループ
	寝て待つ(待機)

	やることがあるかどうか配送リスト(e.g. $ACTIVE_LIST)と
	$MSEND_RCを元に判定。

	たまった記事があれば配送

	データファイルのUPDATE
   }


これをどう実行するか?ということですが、システムが勝手に一定時間ごとに
チェックしてくれるわけではありません。システムに

	一定時間ごとに仕事がないかチェックしろ!

と教える必要があります。それが「cron をしかける」という意味です。

『まとめおくりを行う時間間隔』と『まとめるやり方』はユーザごとに自由に
設定できます。設定はユーザが自分でリモートでコントロールできます。
matome もしくは digest というコマンドです。コマンドについては後の節で
説明します。
#ちなみに matome というコマンドと digest というコマンドは同じです。

ちなみにプログラム群のそれぞれどの部分に対応するかというと

   for(;;) {		(cron)
	寝て、待つ	(cron)
	やることがあるかどうかチェックする	(msend.pl)
	やることがあるなら エントリ(actives の m= 部分)に従って
	実行する (msend.pl)
	(どこまで送ったかの記録を var/log/msendrc というファイルへ保存)
   }

です。cron の部分はシステムのcronが使えればその方が良いのですが、不可
能なら bin/cron.pl をシステムのcronの代わりに使えばよいわけです。

2.2	まとめおくりサーバ  msend.pl 

まとめおくりを実行する スクリプト

SYNOPSIS
   msend.pl    [ options ] $DIR [ options ]  [ $LIBDIR [ options ] ]

   * fml.pl msend.pl fmlserv.pl は同じ引数のとりかたをします。
     #注意: fml_local.pl は MH を意識してるので異なります。

オプションと引数が共存する時は引数が - ではじまるならオプション、それ
以外は directoryの変数 だと仮定します。順番は関係ありませんdirectory 
に関しては そのdirectoryが存在すれば引数の順に $DIR、$LIBDIR にセット
されます。

次のようなオプション及び long line options を取ります。

   -d		デバッグモード
   -bt   	アドレステストモード (Become Test)
		(メンバーチェックのところまで。
		MLへの配送やコマンドは実行しない)
		いまのところ debug mode とかわらへんねん:-)
   -bd		デーモンモード(Become Daemon)
   -sOPT $OPT 	をセットする。(e.g. -sdebug == -d)
   -uOPT $OPT 	をオフする。  (e.g. -udebug は $debug = 0; と同じ)
   -lfile	file を $LOAD_LIBRARY 変数に代入する 
		e.g. -llibfml.pl 
   -q		quiet mode (エラーとかWarning以外は何も出力しない)
		POSIX の cron では OUTPUT をひろうので、-q なら
		エラー時以外はメールが来ないようにするため

2.3	crontab の見本

makefml で newml すると $DIR/crontab に cron の設定の見本ができていま
す。(以下の説明では $DIR は各MLのHOMEです(config.phのある場所))。

4.4BSD では各個人ごとに cron の設定が可能です。その場合、

   (shell prompt)% crontab $DIR/crontab 

を実行することで個人ごとのcronが設定できます。$DIR/crontab は例えば

0 * * * * /usr/libexec/fml/msend.pl /var/spool/ml/Elena /usr/libexec/fml

のように書きます。

上述のように「まとめおくりは msend.pl が行ないますが、自動では行なえま
せん。1時間に一回 msend.pl を実行しなさいとマシンに教える」設定が必要
です。それがこの cron の設定なわけです。

[歴史]
	プログラムの名称 msend.pl (旧 MSendv4.pl)

最初実験プロジェクトのつもりではじめた時の version 4 というのがついた
MSendv4.pl というプログラム名のまま使ってきましたが、msend.pl に変更し
ました。

2.4	プログラムのログファイル $MSEND_RC (名称が変更されました)

デフォールトが MSendrc -> var/log/msendrc に変更されています。
fml 1.x から version up する時に問題になるかも知れません。

config.ph で $MSEND_RC が明示的に指定していないと msend.pl は
$MSEND_RC を定義してくれと警告を(logファイルへ)吐くでしょう。

まとめおくりが"よきにはかって"動くようにすることはできるのですが「中途
半端に動くより今何をやっているか?を管理者が知っていること」を重視して、
わざと $MSEND_RC を明示的に指定してくれというようになっています。

#注意: 実は fml の他の部分はほとんどよきにはからえで動きます(^^)
#まとめおくりが例外です。それは間違って大量のメールを送ったりしては大
#変だからです。

2.5	コマンドで各ユーザーごとにどういうふうに送るかを決めること

fml-1.4.1 以降、各ユーザーごとにまとめ送りの様式を決めることができま
す。デフォールトは UNIX FROM の gzip したフォーマットです。

各ユーザはコマンドをサーバに送ることで、自分で設定を変更することがで
きます。

例: 3時間おきにUNIX FROMの形で送って欲しい場合

	matome 3u

をコマンドとして送ります。UNIXのSHELL上なら

   (shell prompt)% echo "matome 3u" | Mail コマンド用のアドレス

ですね。

2.6	まとめ送りメールに付くSubjectの設定

	$MSEND_SUBJECT_TEMPLATE

という変数があります。これは

    Digest _ARTICLE_RANGE_ _PART_ _ML_FN_

のように設定されていて、内部で

	   _ARTICLE_RANGE_  <=>    Article 768
	   _DOC_MODE_       <=>    [last:10 tar + gzip]
	   _PART_           <=>    (1/4)
	   _ML_FN_          <=>    $ML_FN (here is "(Elena ML)") 

のように変換して、メールの subject: は

   Digest Article 768 (1/1) (Elena ML)

のようになります。この変数を適当にカスタマイズすれば

	(1/1) を削る(_PART_を切る)
	_DOC_MODE_ を加えてドキュメント形式を表示する

とかが簡単にできます。これにより$NOT_SHOW_DOCMODE (CFVersion 2) や 
$MSEND_DEFAULT_SUBJECT は obsolete になりました。

2.7	まとめ送り処理のHOOK

$MSEND_START_HOOK は実際の配送作業の始まる直前に評価されます。

$MSEND_HEADER_HOOK は msend の Subject: 等を変更する場合に使用します。

2.8	まとめ形式のデフォールト
../internals 5.2

gzip で複数のファイルを一つにして送るのがデフォールトですが、 

	$MSEND_MODE_DEFAULT

の値で、まとめ送りサーバの設定を変更することが出来ます。使えるパラメー
タは $MGET_MODE_DEFAULT と同様です。

なお便利なように、これらの簡易設定があります。

(After config.ph CFVersion 3)

	$MSEND_MODE_DEFAULT = "rfc1153"    (default RFC1153)
	$MSEND_MODE_DEFAULT = "rfc934"	   (default RFC934)

に設定する(詳細以下)。

#昔は (config.ph CFVersion 2)
#
#	$USE_RFC1153_DIGEST	デフォールトをRFC1153
#	$USE_RFC1153		デフォールトをRFC1153
#	$USE_RFC934		デフォールトをRFC934
#
#でした。CFVersion 3 以下の config.ph の場合は自動的に補正/変換します。

例:
	まとめおくりのデフォールトを RFC934 へ

	$MSEND_MODE_DEFAULT = "rfc934";

まとめおくりで、0はデフォールトのUNIX FROMで区切られたメールを送り出す
が、1なら次のような形のものを送るようになる。これは mh のburstで複数の
mailに展開できます。#あと、どういうソフトがあるのか知らない…:-)

[934形式の例]

	------- Forwarded Message

	From: uja
	Subject: daa 

	ちまりちゃんもいいわね、いいわね。ねこめ〜わくもいいわねぇ
	しまちゃんかわいい

	------- Forwarded Message

	From: uja
	Subject: Re: daa

	あおいちゃんパニック もいいけど せいふくもの もよくてよ

	--fukachan@けろちゃんご〜ご〜

	------- Forwarded Message

例:
	まとめ送りのデフォールトを RFC1153 digest へ

	$MSEND_MODE_DEFAULT = "rfc1153";

これには、それぞれまとめた束に、通し番号をつけなければなりません。よっ
てまとめおくりのデフォールトを1153に統一することになります。ユーザがコ
マンド matome 3 としても、 gzip ではなく 1153 形を意味するようになり
ます。この形式では通し番号はばらばらで各ユーザ毎に適当についてます。
To hack RFC1153, see librfc1153.pl.

もし細かい所を変えたい場合は librfc1153.pl でフォーマットを決めてくだ
さい

RFC1153 をデフォールトに変更すると、1153はまとめおくりの記事に番号をつ
けるので、個人個人に1153で送ると人によって番号が食い違い、矛盾がおきて
しまいます。
#NetNewsなんかで1153形式を見ればわかるとおもうんですが…

まぁ番号を気にしないならいいんですが…

[注意]
一時期デフォールトで 3時間に強制的に設定しておいてある version があり
ますが、ようは番号の整合性をとるためです。1時間おきの1153送りの人と、3
時間おきの1153送りの人、があると番号が食い違ってしまいます。番号の整合
性を無視すれば、どうでもいいことなんですが…。とりあえず、この部分はコ
メントアウトしてあります(95/6/27)

2.9	msend.pl のコマンド一覧 (help fileより)

○まとめ送り希望の方へ:(基本的に N時間“おき")
なお digest と matome は同じコマンド(引数も当然同じ)です。
matome 数字(0-23)	配送時間は実はmodulusで決めています
			if (0 == (24 % time)) { 配送();} 
			だから 17 なんてやっても一日一回と同じです(_o_)
			様式 default は gzip した Unix From つきのファイ
			ルの固まり
matome 数字(13-36)	上の特別の場合で、一日一回N時にまとめおくり
			13〜36の数字がこのケースに当てはまります
			午前5時に一回だけまとめおくり慕いときは、
			24+5=29 をおくりこんでください。午後5
			時は17でいいんですが、午前中はこうしないと判
			別がつかないので…
   例:
	matome 数字u	plain(unpack)、つまりplain textを
	matome 数字i 	lha + ish でまとめて送ります
   オプション:
		オプションなしはGZIP(UNIX FROM)

	u	PLAIN-TEXT(UNIX FROM)
	uf	PLAIN-TEXT(UNIX FROM)
	i	lha + ish 
	ish	lha + ish 
	mp	MIME/Multipart	PLAIN-TEXT
	d	RFC1153 format 	PLAIN-TEXT
	b	RFC934 format 	PLAIN-TEXT(mh-burst)
	rfc934	
	ish	lha + ish 
	lhaish
	i
	li
	lu	lha + uuencode
	lhauu
	unpack	PLAIN-TEXT(UNIX FROM)


matome 0		普通の配送へ戻す

   例:
   matome 1		まとめ送り 1時間に一回(gzipd)
   matome 2		まとめ送り 2時間に一回(gzipd)
   matome 2u		まとめ送り 2時間に一回(plain text)
   matome 2mp		まとめ送り 2時間に一回 MIME/Multipart形式で
   matome 17		まとめ送り 一日一回と同じ(gzipd)
			#この場合は17時に来る
   matome 29		まとめ送り 一日一回と同じ(gzipd)
			#この場合は午前5時に来る
			#matome 5 は5時間“おき” という意味

2.10	まとめ送りがなかった msend がメールを出す設定


	$MSEND_NOTIFICATION = 1;

の時 msend は一日記事がなかったので「まとめ送りをしなかった」ことをメー
ルでMLのメンバーに知らせます。

	$MSEND_NOTIFICATION_SUBJECT (default "Notification $ML_FN")

はその時のメールの Subject: です。

2.11	まとめ送りの時には X-ML-Info: は必要ない

	$MSEND_NOT_USE_X_ML_INFO = 1;

で付けないようにします(注意: $NO_ML_INFO から名称変更)。

2.12	捕捉:まとめおくりと$ACTIVE_LISTと$MSEND_RCと実際の動き…

activesがこんなかんじだとします。

	-------- actives --------
	katri
	pollyanna	m=6u
	-------- actives --------

	cron で一時間に一度 msend.pl を呼びます。

			↓

	activesをしらべて pollyanna はまとめおくりで6時間に一度で
	gzipかけないで配送(uがついてるから)希望だとわかる。
	この時に各ユーザごとにどういうふうに送るかを読み取っています

			↓

	もし 今の時間 % 6 が0(mod 6) なら、つまり、6、12、
	18、24時なら、配送することにして
	#もし 29 なら 一日一回午前5時です。

			↓

	var/log/msendrc(旧 MSendrc)という、今までの配送記録とスプールの記事
	のたまり具合を比べ送ってない分がどの記事か?を決定する。
	記事がない場合はそのまま終り

			↓

	送ってない分をスプールから取り出して配送する。

つまり 
	「特定時間になるとあらかじめためてあったメールを送る」
のではなく、
	「特定時間になるとactivesの情報に基づき、その時間に送ることに
	なっている人に、まだ送っていなかった分のメールをスプールから取
	り出して送る」
わけです。

そのため各個人ごとに送り方を完全にカスタマイズすることが可能になるわけです。
また送る時の記事のまとめ方も mget コマンドと同じだけの自由度が選べます。
../internals 5.0

2.13	まとめおくりの いつ送るか?の判定を変える

msend.pl の sub MSendP で行っています。この部分の変更をすればできます
が hard coding になってしまいますね。

例: 今の設定

   if (($ID - $Request{$who}) >= 0) {
	送るべきメールがあるか?

	return 1 if(0 == ($HOUR % $When{$who}));
	$When{$who} おきに送るのだが、いまの時間は?

	return 1 if($When{$who} > 12 && ($HOUR + 24 == $When{$who}));
	一日一回送る人には 今がその時か?
	…

2.14	まとめおくりをデフォールトにする

contrib/msend-anytime にテスト版の「リアルタイム配送はしないで全員にま
とめおくりをする場合のパッチ」があります。

設定はこのパッチをあてて -a と -A オプションつきで msend.pl を起動する
ように改造します。まとめ送りのタイミングは cron から起動する時間で調節
して下さい。

まとめ送りの設定をしていないユーザへのまとめ送りのモードは

	$MSEND_MODE_DEFAULT 

で決まります。

2.15	捕捉:システムの cron の代わりに bin/cron.pl を使う場合
2.17

cron は 昔からある Unix の Daemon process で 1分に一回起きて、やるこ
とがないか調べて、やることがあれば、実行、しなければ、60秒間ねて待つ 
ということをします。

Vixie cron をいれてるとか POSIX なOSは個人のcronエントリが設定できます。
歴史的な流れを見てる人には見えてるとおもいますけど、crontab の Syntax 
は 4.4 ですが bin/cron.pl は4.3BSD用に開発したものです。今時の cron は
ユーザー権限で走ってくれるとおもうのですが、詳しくは man cron でマニュ
アルを読んでください。

『ユーザがUnixマシンの機能を使えるサービス内容で、それにお金を払ってい
る契約の場合』(契約書はよく読んでくださいね、そうでないところもありま
す)は迷うことなく加入しているプロバイダに聞いて見るのが確実でしょう
(^^)

どうしてもわからない時は、そのマシンの管理者に尋ねてみるとよいでしょう。
ただボランティアで管理者をやってるケースも多いですからできるだけ自分で
やることが望ましいです。
#ネットワーク管理者は激務なのでいたわってあげてください(お願い)

2.16	一週間に一度まとめ送りをするには?
../utility_programs 6.25

bin/weekend-msend.sh に見本があるのでみてみよう。朝と夕方だけなどの応
用も全部同様ですね。
../utility_programs 6.25
../utility_programs 6.25

2.17	Cron (FML Vixie cron compatible program, bin/cron.pl)

○ cron.pl って何?
cron.pl(例: /usr/local/fml/bin/cron.pl)はシステムにユーザごとに定義で
きる cron がない場合に使います。まずはユーザごとに定義できる cron がな
いかどうかを調べて下さい。まずはマニュアルを引いてみて下さい。
	man cron
	man crontab
を試してみるのが最初です。

○ どう動くの?
動きとしてはOS附属の cron と同じです。つまり1分に一回起きて今やるべき
ことがあるかどうかを確認するためにcrontabを見ます。そしてするべきこと
があればそれを実行します。

○ cron.pl は誰がいつ走らせるか?
管理者が手で起動してもいいし、fml.pl が cron.pl を走らせてるようにして
もよいです。注意として fml.pl から cron.pl を走らせると各MLごとに一
つのcronが走って無駄です。複数のMLがある場合は一つの cron.pl で複数
のMLを担当するような設定ファイルを書くのが良いです。

fml.pl から起動すると何回も cron.pl を起動しますが、複数は走りません。
最初の一個以外は自殺します。各MLごとに一つです。$CRON_PIDFILE
($DIR/var/run/cron.pid)というファイルにプロセス番号を保存し一意性を保
証しています。

○ cron.plは一度起動するとずっと走っている?

理想的としてはそうです。が、cron.pl が知らない間に落ちてるかもしれない?
という可能性もあります。システムの cron なら大丈夫ですが、マシンがリブー
トしたら当然FMLのcronは止まったままになってしまいます。そのため何らか
の方法で定期的に起動しなおしてやる必要があります。


○ 注意
また長く走り過ぎておかしくなる場合も考慮してデフォールトでは24時間で次
の cron.pl を起動しなおします。これは予防策であって必ずしもする必要は
ありません。-n オプションをつけるとずっと走り続けるようになります。

○ コマンドシンタックス

SYNOPSIS
	cron.pl [-a] [-d] [-b43] [-fcrontab] [-bd] $DIR [$LIBDIR]

    -d                debug mode 
    -a                run eternally(default: 180sec. = 60sec. * 3times) 
    -n                working all times without RESTART
    -mtimes           run from now to (60 * times) sec. after 
    -fcrontab-file    alternative crontab 
    -h                show this help and exit 
    -bd		      daemon (Become Daemon) 
    -bOSTYPE          -b43(OSTYPE = 43): 4.3BSD Like. not mailed to you 

-b43 オプションは 

	$CRON_NOTIFY    = 0; (default 1)

ということをします。デフォールトでは cron が何らかの処理をした場合はそ
のログをそのユーザに知らせます。

またデフォールトでは cron.pl はデーモン化しません。

	-onotty

オプションをつけると自分でデーモン化します。
うまくいかないOSがありうることを考慮してデフォールトでは

	$NOT_USE_TIOCNOTTY = 1;		# no ioctl

つまりデーモンにならないようになっています。

2.18	Vixie Cron

4.4BSD には Paul Vixie の書いた各ユーザごとに cron を定義できる cron 
が入っています。これがあるなら cron.pl は要らないです。詳しくはシステ
ムのマニュアルを見て下さい。
#全然関係ないけど vixie enterprise にftp.NetBSD.ORGとかあります。
#Vixie偉い

cron (8) - daemon to execute scheduled commands (Vixie Cron)
crontab (1) - maintain crontab files for individual users (V3)
crontab (5) - tables for driving cron

古いOSにはありません。しかし元々入っていなくても管理者の人がインストー
ルしているかもしれません。探してみる価値/聞いてみる価値はあります。

FMLのcron.plはあくまでも『そういう cron を提供してくれていないOS』でま
とめ送りを支援するためのものです。こういうサービスはOSが提供してくれる
のが本筋というべきでしょう。

2.19	cron.plを自動的に起動するようにするためには?

システムが定期的に何かをしてくれないので、cron.pl をなんとかして(疑似
定期的に)起動したいわけです。問題はどう起動するか?だけです。

まず起動自体は

	% cron.pl $DIR(config.phの場所) $LIBDIR(libsmtp.plとかの場所) 

の形で起動します。
#注意: Argument がないと、その環境の $HOME にいってしまう

問題はどうやって定期的に起動をトライするかですが、例えば

   1. たとえば ~/.login で cron.pl を起動するとか(すでに走っていれば走
      らないから大丈夫)…

   2. loginしたとき、まめに(手動で)たちあげるとか…

   3. MLサーバにメールが来たときに起動させる↓とか…

が考えられます。3の設定としては config.ph に


	$CRON_PIDFILE = "$DIR/var/run/cron.pid";
	$CRONTAB      = "$DIR/etc/crontab";

	$FML_EXIT_PROG = "$LIBDIR/bin/cron.pl $DIR $LIBDIR -a";

をつけたします。
#いずれも適当にパスとかは変えてください

cron.pid は cron.pl の pid を記録するファイルです(/var/run/cron.pidに
相当するもの)。

crontab は システムの /var/cron/tabs/$USER (4.3BSDの/etc/crontab)に相
当するものです。makefml newml した時に各MLの HOME (config.phのある場
所)には crontab という見本(4.4BSD形式) が作られます。4.4BSD 形式ではこ
れを使えばまとめ送りの設定ができます。

[Example]
	% makefml newml elena
	  ...
	% cd /var/spool/ml/elena
	% crontab crontab

***注意***
cron.pl は 4.4BSD FORMAT を理解します。4.3BSDの形式ではありません