ldap関連のコマンドでldapのエントリの編集ができるldapmodifyというヤツがいます。
これをコマンドライン上で利用してわざとエラーを発生させます。
$ ldapmodify (オプションは省略)
adding new entry radiusname=hoge,****
ldap_add: Already exists
hogeというユーザがいるのにさらにhogeというユーザを追加しているので「Already exists」というエラーが発生する。ちなみにこのエラーメッセージは標準出力ではなく、エラー出力経由で表示されてます。
そして今度は出力をファイルにリダイレクトさせます。
$ ldapmodify (オプションは省略) > ./log.txt 2>&1
$ cat ./log.txt
ldap_add: Already exists
adding new entry radiusname=hoge,****
なんとエラーメッセージが最初に来るという怪奇現象が発生。どうもエラー出力が出た後に、標準出力が出ている模様。
ldapmodifyをスクリプトの中に組み込んで、エラー処理も行いたい場合、これが非常に厄介。例えば複数のエントリを編集しようとして一部がエラーになった場合、
$ ldapmodify (オプションは省略) > ./log.txt 2>&1
$ cat ./log.txt
ldap_add: Already exists
adding new entry radiusname=hoge,****
adding new entry radiusname=fuga,****
hogeとfuga、どっちのユーザがエラーになったのかが全く判断付かない。ちなみにコマンドラインで直接実行すればエラーメッセージは期待通り「adding new~」というメッセージの下に出るので問題ない。
この謎な現象をさらっと調べた感じ、どうもこの仕様が原因っぽい。
標準出力→バッファリングされる
エラー出力→バッファリングされない
なわけでエラー出力は都度出力され、標準出力はバッファリングされてから出力されているくさい。なんだこれはーorz
というわけでバッファリングさせなければいいのかと、perlとかのスクリプトを上にかぶせて色々試してみたんだけど、どれも空振りだった。
#!/usr/bin/perl
$| = 1;
$a = `ldapmodify (オプションは省略) 2>&1`;
print $a;
exit;
とか
#!/usr/bin/perl
close(STDOUT);
open(STDOUT,">&STDERR");
$a = `ldapmodify (オプションは省略) 2>&1`;
print $a;
exit;
とか、なんか他にも色々。。。
Cとかでもsetbuf()でバッファリング無効にした後にldapmodifyを実行するやつを作ってみたけど、やっぱり結果は同じ。
…んー、やっぱあれかな、 ldapmodifyコマンド自体が標準出力のバッファリングを無効にするとかしてないとダメなのかな。よくわからない。
というか解決の糸口が全くみつかりませんorz
あ、ちなみにOSはsolarisです。Linuxだとどうなるかは試してないのでわかりません。
あと基本的にbashで確認してますが、shもtcshでもダメでした。
そして色々調べてたらこんな記事を発見。
ITDS V5.2のldapmodifyコマンドでは-cオプションでエラー発生時の継続処理をサポートしますが、エラー内容のダンプを-Sオプションでファイルに書き出す機能はサポートしておりません。
標準出力、標準エラー出力をリダイレクトするなどの方法で、代替する必要があります。
その代替手段がまともに使えないのですが…。みなさん困ってないんですかね?
今のところうちの逃げ方としてはldapmodifyに-vの冗長化オプションを付けて、そちらで判定させようと思っています。ldapmodifyを1処理毎に分けて実行する方法もあるけど、スクリプトが遅くなりすぎるのでできればやりたくないかな。。。
とういわけで誰かもっといい解決方法を知ってたら教えてください(T_T)
作成日:2009/07/12 12:16:29