コメント |
|
|
# 引用の順番を入れ換えてます。
> # 最初に makewhatis.cron が実行されたときよりもタイムスタンプの
> # 新しい man ファイルがないと、-u オプションでデータベースが
> # 更新されないとすると、アプリケーションをインストールしても
> # それに付属する man が登録されないこともあるわけですね。
少し見てみたのですが、これは find のオプションで
-cnewer を使えば対応できそうな感じです。
あと、
> というわけで、何らかの形で一度 makewhatis -w をやっておく
> 必要があるのではないでしょうか。
については、
1) インストーラで、インストールの最後に実施する。
2) makewhatis.cron で、/var/cache/man/whatis の
存在チェックをして、無いときは -w 付きで実行する。
3) パッケージの postinstall でとりあえず -w を実行する。
等の方法が思い付きますが、どれが良いでしょうか。
# 他にもっと良い方法がありそうな気もしますが。 |
|
|
|
すこし考えていたので、返事が遅くなり、失礼しました。
もっとも、考えても結局わからなかったのですけれど。
> > # 最初に makewhatis.cron が実行されたときよりもタイムスタンプの
> > # 新しい man ファイルがないと、-u オプションでデータベースが
> > # 更新されないとすると、アプリケーションをインストールしても
> > # それに付属する man が登録されないこともあるわけですね。
>
> 少し見てみたのですが、これは find のオプションで
> -cnewer を使えば対応できそうな感じです。
/usr/sbin/makewhatis の
-u) findarg="-newer /var/cache/man/whatis"
を
-u) findarg="-cnewer /var/cache/man/whatis
にするのですか。それだけですむなら自分でもできそうなので、
試してみました。たしかに cron 経由なら、これで問題なさそうです。
しかし、
# /etc/cron.daily/makewhatis.cron
とか、
# /usr/sbin/makewhatis -u -w
などとすると、whatis データベースがうまく更新されません。
ファイルの日付が新しくなるだけで、サイズは元のままです。
理由は、おそらく makewhatis の実行途中に /var/cache/man
/whatis が何度も作りなおされるせいだろうと、想像できます
(その結果、新しくインストールした man の ctime より whatis
の日付が新しくなってしまう)。それならば、cron 経由で動かした
ときは、どうして内容まできちんと更新されるのでしょう。
ここで行き詰まってしまいました。
> > というわけで、何らかの形で一度 makewhatis -w をやっておく
> > 必要があるのではないでしょうか。
>
> については、
>
> 1) インストーラで、インストールの最後に実施する。
>
> 2) makewhatis.cron で、/var/cache/man/whatis の
> 存在チェックをして、無いときは -w 付きで実行する。
>
> 3) パッケージの postinstall でとりあえず -w を実行する。
>
> 等の方法が思い付きますが、どれが良いでしょうか。
どれでもよさそうですね。強いて言うならば−−、
1) は、apt-get でアップグレードすることもあるでしょうから、
その場合も計算に入れておいた方がよいと思います。
3) は 2) よりもきれいな方法だと思いますが、パッケージの
インストール中に実行されるわけで、比較的古いマシンで
がんばっている人には、インストールに時間がかかって、
ちょっといらだたしいかもしれません。
というわけで、2) でしょうか。3) でもいいですけれど。
--
長南 |
|
|
|
> /usr/sbin/makewhatis の
> -u) findarg="-newer /var/cache/man/whatis"
> を
> -u) findarg="-cnewer /var/cache/man/whatis
> にするのですか。それだけですむなら自分でもできそうなので、
> 試してみました。たしかに cron 経由なら、これで問題なさそうです。
>
> しかし、
> # /etc/cron.daily/makewhatis.cron
> とか、
> # /usr/sbin/makewhatis -u -w
> などとすると、whatis データベースがうまく更新されません。
> ファイルの日付が新しくなるだけで、サイズは元のままです。
>
> 理由は、おそらく makewhatis の実行途中に /var/cache/man
> /whatis が何度も作りなおされるせいだろうと、想像できます
> (その結果、新しくインストールした man の ctime より whatis
> の日付が新しくなってしまう)。それならば、cron 経由で動かした
> ときは、どうして内容まできちんと更新されるのでしょう。
> ここで行き詰まってしまいました。
とのことでしたので、/etc/cron.daily/makewhatis.cron を
以下のように書き換えてテストしてみました。
$ cat /etc/cron.daily/makewhatis.cron
#!/bin/sh
LOCKFILE=/var/lock/makewhatis.lock
# the lockfile is not meant to be perfect, it's just in case the
# two makewhatis cron scripts get run close to each other to keep
# them from stepping on each other's toes. The worst that will
# happen is that they will temporarily corrupt the database...
[ -f $LOCKFILE ] && exit 0
touch $LOCKFILE
if [ ! -s /var/cache/man/makewhatis ] ; then
makewhatis -w
else
makewhatis -u -w
fi
rm -f $LOCKFILE
exit 0
単に案 2) の通りに修正しただけですが、これであれば
# /etc/cron.daily/makewhatis.cron も問題無く
実行できました。
> どれでもよさそうですね。強いて言うならば−−、
> 1) は、apt-get でアップグレードすることもあるでしょうから、
> その場合も計算に入れておいた方がよいと思います。
> 3) は 2) よりもきれいな方法だと思いますが、パッケージの
> インストール中に実行されるわけで、比較的古いマシンで
> がんばっている人には、インストールに時間がかかって、
> ちょっといらだたしいかもしれません。
> というわけで、2) でしょうか。3) でもいいですけれど。
他に問題が無ければ 2) で行けそうですね。
# 状態を割当済みに変更しておきます。 |
|
|
|
> $ cat /etc/cron.daily/makewhatis.cron
> #!/bin/sh
>
> LOCKFILE=/var/lock/makewhatis.lock
>
> # the lockfile is not meant to be perfect, it's just in case the
> # two makewhatis cron scripts get run close to each other to keep
> # them from stepping on each other's toes. The worst that will
> # happen is that they will temporarily corrupt the database...
> [ -f $LOCKFILE ] && exit 0
> touch $LOCKFILE
> if [ ! -s /var/cache/man/makewhatis ] ; then
> makewhatis -w
> else
> makewhatis -u -w
> fi
> rm -f $LOCKFILE
> exit 0
>
> 単に案 2) の通りに修正しただけですが、これであれば
> # /etc/cron.daily/makewhatis.cron も問題無く
> 実行できました。
# 上記の /var/cache/man/makewhatis は whatis ですね。
これは /usr/sbin/makewhatis を
-u) findarg="-cnewer /var/cache/man/whatis"
にしての話ですか。
そうならば、次のような結果になると思います。
1) /var/cache/man/whatis が存在しないか、サイズ 0 のとき。
1a) cron から: OK
1b) /etc/cron.daily/makewhatis.cron の手動実行: OK
2) /var/cache/man/whatis のサイズが 0 ではないとき
(新しくインストールした man ファイルを登録するときは、
whatis データベースが既に存在しているはずですから、
こちらが常態)。
2a) cron から: OK
2b) /etc/cron.daily/makewhatis.cron の手動実行: Not OK
# より正確に言うと、2b) は「Not OK のこともある」でしょう。
# manpath は /usr/share/man/ja:/usr/share/man:
# /usr/X11R6/man の順番ですから、新しくインストールされた
# man ファイルが日本語 man である場合は、/var/cache/man/
# whatis の最初の書き換えで情報が取り込まれるので、きちんと
# 反映しそうです。
# それに反して、英語 man の場合は、whatis が一度書き直され、
# 日付が更新された後で find -cnewer が実行されることになる
# ので、うまく行かないだろうと思います。
まあ、makewhatis.cron を手作業で実行する必要なんてふつう
ありませんから、気にしなくてもよいのかもしれません。
とは言え、手動実行でも結果が変わらない方が、よいと言えば
よいわけですけれど。
それはそうと、何故 cron では問題なく実行できることが、
手動ではうまく行かないのでしょう。
/usr/sbin/makewhatis をちょっと書き変えててみました。
おもな変更は、if [ -f /var/cache/man/whatis ] 以下を
ループの外に追い出したことです。添付ファイルにオリジナルと
変更したものとの diff -u の出力を付けておきます。
このように書き変えると、cron 経由でも makewhatis.cron の
手動実行でも同じ結果が得られます。しかし、オリジナルの
makewhatis が manpath(mandir) ごとに /var/cache/man/
whatis を書き直していることには何か理由があるのでしょう。
それで、こんなことをやってよいものかどうか、まったく
自信がありません。
--
長南 |
|
|
|
> > 単に案 2) の通りに修正しただけですが、これであれば
> > # /etc/cron.daily/makewhatis.cron も問題無く
> > 実行できました。
>
> # 上記の /var/cache/man/makewhatis は whatis ですね。
すいません。そうです。
> これは /usr/sbin/makewhatis を
> -u) findarg="-cnewer /var/cache/man/whatis"
> にしての話ですか。
はい。
> そうならば、次のような結果になると思います。
> 1) /var/cache/man/whatis が存在しないか、サイズ 0 のとき。
> 1a) cron から: OK
> 1b) /etc/cron.daily/makewhatis.cron の手動実行: OK
> 2) /var/cache/man/whatis のサイズが 0 ではないとき
> (新しくインストールした man ファイルを登録するときは、
> whatis データベースが既に存在しているはずですから、
> こちらが常態)。
> 2a) cron から: OK
> 2b) /etc/cron.daily/makewhatis.cron の手動実行: Not OK
>
> # より正確に言うと、2b) は「Not OK のこともある」でしょう。
> # manpath は /usr/share/man/ja:/usr/share/man:
> # /usr/X11R6/man の順番ですから、新しくインストールされた
> # man ファイルが日本語 man である場合は、/var/cache/man/
> # whatis の最初の書き換えで情報が取り込まれるので、きちんと
> # 反映しそうです。
> # それに反して、英語 man の場合は、whatis が一度書き直され、
> # 日付が更新された後で find -cnewer が実行されることになる
> # ので、うまく行かないだろうと思います。
2a)までは想定できていたのですが、2b)は想定外でした。
なぜなんでしょう……。
> まあ、makewhatis.cron を手作業で実行する必要なんてふつう
> ありませんから、気にしなくてもよいのかもしれません。
> とは言え、手動実行でも結果が変わらない方が、よいと言えば
> よいわけですけれど。
>
> それはそうと、何故 cron では問題なく実行できることが、
> 手動ではうまく行かないのでしょう。
調べてみましたが、原因は分かりませんでした。
ちゃんと makewhatis を読んでみると、原理的には 2a)でも
Not OKになならないとおかしいとは思うのですが、なにか
実行する条件とか環境が違うのが影響しているのでしょうか。
> /usr/sbin/makewhatis をちょっと書き変えててみました。
> おもな変更は、if [ -f /var/cache/man/whatis ] 以下を
> ループの外に追い出したことです。添付ファイルにオリジナルと
> 変更したものとの diff -u の出力を付けておきます。
時間を取って読んでみましたが、この変更で(私には)問題無い
ように思えます。
ただし長南さんも書かれているように、
> このように書き変えると、cron 経由でも makewhatis.cron の
> 手動実行でも同じ結果が得られます。しかし、オリジナルの
> makewhatis が manpath(mandir) ごとに /var/cache/man/
> whatis を書き直していることには何か理由があるのでしょう。
> それで、こんなことをやってよいものかどうか、まったく
> 自信がありません。
というのは確かに気になります。
そこで、対応方法をちょっとだけ変えて、
1. 157行目の for loop に入るより前に /var/cache/man/whatis を
作業用のファイルにコピー
2. それ以降の作業で内容を書き出す先を、上記の作業用ファイルに
変更
3. 処理の一番最後に作業用ファイルを /var/cache/man/whatis
に mv する
という方法にすれば
a) find -cnewer /var/cache/man/whatis は処理の最後まで
有効に働くようになる。(上記 2b 以降のコメントにある
現象を防ぐことができる)
b) 複数回 manpath 毎に /var/cache/man/whtais を書き直して
いるオリジナルのやり方を変えなくてよい。
となり、不安も解消できると思います。
# 時間が取れなくて patch まで準備できてません。すいません。 |
|
|
|
了解しました。patch を出してくださったら、試してみる
ことにします。
ところで、
> 調べてみましたが、原因は分かりませんでした。
> ちゃんと makewhatis を読んでみると、原理的には 2a)でも
> Not OKになならないとおかしいとは思うのですが、なにか
> 実行する条件とか環境が違うのが影響しているのでしょうか。
そうなんですよね。私もその点が釈然としなかったのです。
ひょとすると、/etc/cache/man/whatis に対する書き込み命令と、
実際の書き込みの間の時間差に関係があるではないか。そうだと
したら、man ファイルが /usr/X11R6/man にある場合は、cron
経由でも man ファイルが登録されないかもしれない。そう思い
ついたので、以下のような悪戯をやってみました。
/usr/sbin/makewhatis は、「-u) findarg="-cnewer
/var/cache/man/whatis"」の部分だけを変更したものです。
# whatis Xconfigurator
Xconfigurator (1x) - configure XFree86 server and display
# rpm -e Xconfigurator
# /usr/sbin/makewhatis -w
# whatis Xconfigurator
Xconfigurator: nothing appropriate
# rpm -ivh Xconfigurator-5.03-0vl1.i386.rpm
(/etc/crontab の書き換え)
(cron による /etc/cron.daily/makewhatis.cron の実行)
# whatis Xconfigurator
Xconfigurator: nothing appropriate
どうやら、2a) がうまく行くように見えたのは、man ファイルが
/usr/share/man/ja にある場合ははもちろん、 /usr/share/man に
ある場合も、/var/cache/man/whatis へのに書き込みが実際に
行われる前に、find -cnewer を実行していたかららしい。
cron による実行とスクリプトの手動実行では、書き込みの命令と
実際の書き込みとの時間差に相違があるようです。そういうもの
なんでしょうか。
--
長南 |
|
|
|
> 了解しました。patch を出してくださったら、試してみる
> ことにします。
かなり手間取りましたが、とりあえずなんとかいけそうな
感じになりましたので、追試して頂けると助かります。
修正の内容ですが、
1. 添付の patch を /usr/sbin/makewhatis にあてる
2. /etc/cron.daily/makewhatis.cron を以下のように
ように変更する。(LANGを指定するだけですが)
--- makewhatis.cron.orig 2006-12-05 23:34:28.000000000 +0900
+++ makewhatis.cron 2006-12-05 23:34:42.000000000 +0900
@@ -9,9 +9,9 @@
[ -f $LOCKFILE ] && exit 0
touch $LOCKFILE
if [ ! -s /var/cache/man/whatis ] ; then
- makewhatis -w
+ LANG=ja_JP.eucJP makewhatis -w
else
- makewhatis -u -w
+ LANG=ja_JP.eucJP makewhatis -u -w
fi
rm -f $LOCKFILE
exit 0
の2つです。
長南さんのリプライを参考に、Xconfigurator ではなく nkf の
パッケージ※を使って色々テストしてみたのですが、
cron による実行でも、手動で makewhatis.cron を実行
しても大丈夫でした。
(※nkf には en/ja 双方の man page が含まれるので)
尚、添付の patch だけだと cron で実行した時に、
man --path の実行結果が異なる(jaが含まれない)
ことに気付いたので、上記のように makewhatis.cron で
LANGを指定するようにしています。
(ここに書くのが良いのかどうか悩ましいですが……)
ハラダ |
|
|
|
makewhatis.cron に LANG=ja_JP.eucJP が必要だというのは、
ちょっと気づきにくいことですね。
さて、inetd、Xconfigurator、nkf パッケージを rpm -e したり、
rpm -i したりして、試してみました。cron 経由でも
/etc/cron.daily/makewhatis.cron の手動実行でも、まったく
問題がありませんでした。
ただ、気になったのですが、whatis.tmp のような、ファイル名を
容易に推測できるテンポラリ・ファイルを作るのは、セキュリティ上
問題ないんでしょうか。……と、偉そうなことを書きましたが、
セキュリティ関係はさっぱりわかりません。whatis.tmp にすると、
どんな危険があるのか、想像することもできないでいます。
それどころか、makewhatis みたいなコマンドに危険なんてないん
じゃないか、とさえ思っています。しかし、makewhatis 自身にも
次のようなコメントが書いてあり、mktemp を使って、テンポラリ
ディレクトリを作っているわけです。それで、そういうところを見ては、
ついつい不安を感じているということなんですが……。
# Find a place for our temporary files. If security is not a concern, use
# TMPFILE=/tmp/whatis$$; TMPFILEDIR=none
# Of course makewhatis should only have the required permissions
# (for reading and writing directories like /usr/man).
# We try here to be careful (and avoid preconstructed symlinks)
# in case makewhatis is run as root, by creating a subdirectory of /tmp.
と言って、テンポラリファイル作成であまり複雑なことをするのも、
変な気がしますし……。
ふと思い出したのですが、昔の Vine は whatis データベースを
manpath ごとに作っていたような気がします。そこで Vine 2.6
や 2.1 の CD を引張り出して、/usr/sbin/makewhatis を
読んでみました。やっぱりそうでした。Vine 2.1 の makewhatis
が whatis データベースに書き込んでいるくだりはこんな具合でした
(man-1.5h1-4vl2.i386.rpm)。
# kludge for Slackware's /usr/man/preformat
if [ $mandir = /usr/man/preformat ]
then
mandir1=/usr/man
else
mandir1=$mandir
fi
if [ -f ${mandir1}/whatis ]
then
cat ${mandir1}/whatis >> $TMPFILE
fi
sed '/^$/d' < $TMPFILE | sort | uniq > ${mandir1}/whatis
chmod 644 ${mandir1}/whatis
rm $TMPFILE
というわけで、manpath ごとに whatis データベースを書き
直していたのは、古いコードの名残にすぎなかったようです。
だったら、まとめて一回で済ましても、いいんじゃないでしょうか。
そうすれば、whatis.tmp を作る必要もなくなりますし。
Vine 4.0 の makewhatis(man-1.5o-0vl1)のコメントには
こんなことが書いてありますけれど。
# Some distributions make a single big /var/cache/man/whatis file,
# but that leads to problems and bugs.
御参考までに、長くて御迷惑かもしれませんが、 Vine 2.1 時代の
makewhatis を添付ファイルにしておきます。面白いことに、
このときは findarg をこんなふうに指定しています。
-u) findarg="-ctime 0"
"-ctime 0" というのがどういうことか、ピンとこないんですが。
--
長南 |
|
|
|
> さて、inetd、Xconfigurator、nkf パッケージを rpm -e したり、
> rpm -i したりして、試してみました。cron 経由でも
> /etc/cron.daily/makewhatis.cron の手動実行でも、まったく
> 問題がありませんでした。
確認ありがとうございます。
コメント頂いた点について色々考えた結果、
添付のような patch を当てて更新したパッケージを
man-1.5o-0vl2 として VineSeed に upload しました。
> ただ、気になったのですが、whatis.tmp のような、ファイル名を
> 容易に推測できるテンポラリ・ファイルを作るのは、セキュリティ上
> 問題ないんでしょうか。
については、mktemp した dir の下にファイルを追加
するようにしました。
とりあえずこれなら前の patch よりは安全だと思います。
それから、
> というわけで、manpath ごとに whatis データベースを書き
> 直していたのは、古いコードの名残にすぎなかったようです。
> だったら、まとめて一回で済ましても、いいんじゃないでしょうか。
> そうすれば、whatis.tmp を作る必要もなくなりますし。
については、ちょっと悩んだのですが、
> Vine 4.0 の makewhatis(man-1.5o-0vl1)のコメントには
> こんなことが書いてありますけれど。
>
> # Some distributions make a single big /var/cache/man/whatis file,
> # but that leads to problems and bugs.
仮りに処理を変更したとして、具体的にどのような問題を引き起こすか
想像できなかったんですが、やはりこのコメントが気になったので
今の処理をそのまま残すことにしました。
(うまく動いているものは極力いじらない方が安全かなと)
4.0 の errata を発行するかどうかについては別途相談してみます。
ハラダ |
|
|
|
> コメント頂いた点について色々考えた結果、
> 添付のような patch を当てて更新したパッケージを
> man-1.5o-0vl2 として VineSeed に upload しました。
拝見しました。この patch をオリジナルの makewhatis に当て、
例によって nkf と Xconfigurator を入れたり出したりして、
試してみました。問題ありません。
実のところ、わたしは今では「whatis データベースの書き直しは、
一回ですましちゃえ論者」になっています。manpath ごとに
二つめのテンポラリファイルを書き換える必要がわからないので。
とは言え、テンポラリファイルを二つ利用する方法に問題が
あるとも思えません。また、変更をできるだけ小さくするのは
穏当な行き方でしょう。ですから、この patch でよいと思います。
> > # Some distributions make a single big /var/cache/man/whatis file,
> > # but that leads to problems and bugs.
>
> 仮りに処理を変更したとして、具体的にどのような問題を引き起こすか
> 想像できなかったんですが、やはりこのコメントが気になったので
> 今の処理をそのまま残すことにしました。
> (うまく動いているものは極力いじらない方が安全かなと)
Vine 2.1 ぐらいまでの makewhatis スクリプトが manpath
ごとに whatis ファイルを作っていたのは、主として、
スクリプトが途中で中断したときに、実行した仕事をできるだけ
無駄にしないための工夫ではなかったかと思います。
このスクリプトが最初に作られたのは 1992 年ですから、当時の
マシンスピードを考えると、そういう工夫が実用的だったので
しょう。また、テンポラリファイルが大きくなりすぎないための
用心だったのかもしれません。
ですから、もうこのコメントは、あまり気にしないでもよいのでは
ないかと思います。まあ、「処理は小さく分けた方が間違いがない」
という一般論は今でもそのとおりでしょうけれど。
ところで、Seed にある man-1.5o-0vl2.i386.rpm の方も、
ダウンロードして、中身を拝見しました。
/etc/cron.daily/makewhatis.cron と /etc/
cron.weekly/makewhatis.cron がまったく同じようですが、
cron.weekly の方は、LANG=ja_JP.eucJP makewhatis -w
のみにした方がよいのではないでしょうか。もともとここは、
毎日データの追加をして、一週間に一回データベースをきれいに
一から作りなおす、ということになっていたのだと思います。
cron.daily の処理を信用して、/etc/cron.weekly/
makewhatis.cron はなくしてしまう、という行き方もありますね。
--
長南 |
|
|
|
> ところで、Seed にある man-1.5o-0vl2.i386.rpm の方も、
> ダウンロードして、中身を拝見しました。
> /etc/cron.daily/makewhatis.cron と /etc/
> cron.weekly/makewhatis.cron がまったく同じようですが、
> cron.weekly の方は、LANG=ja_JP.eucJP makewhatis -w
> のみにした方がよいのではないでしょうか。もともとここは、
> 毎日データの追加をして、一週間に一回データベースをきれいに
> 一から作りなおす、ということになっていたのだと思います。
すいません。それは知りませんでした。
早速修正したパッケージを 0vl3 として upload して
おきました。 |
|
|
|
> 早速修正したパッケージを 0vl3 として upload して
> おきました。
Seed の man-1.5o-0vl3.i386.rpm を見て、修正を
確認しました。やっぱりこういう確認報告もするべきだった
のでしょうか。必要なさそうだと思って、さぼっていたのですが。
というわけで、この件はクローズしてよいと思います。
--
長南 |
|
|
|
> Seed の man-1.5o-0vl3.i386.rpm を見て、修正を
> 確認しました。
確認ありがとうございます。
状態を完了に変更します。
> やっぱりこういう確認報告もするべきだった
> のでしょうか。必要なさそうだと思って、さぼっていたのですが。
いえいえ。絶対に必要と言う訳では有りません。
もちろん確認していただけると、(0vl2 の時のような)ポカミスが
防げるので大変助かりますが。
errata を出すべきか結論が出てからとも思いましたが、
それは別の場所で相談しておきます。 |
|