トップ回答者
Add-Contentコマンド失敗の要因について

質問
-
現在WindowsEventing6.0系のイベントログを取得する為に、イベントログを取得した後で
Add-Contentコマンドを使ってテキストファイルへ出力させています。
基本は問題なくテキストファイルへ出力が出来ているのですが、時たま失敗いたします。
考えとして、対象のテキストファイルもしくはそのディレクトリへのアクセスや書き込みが出来ない場合(権限やファイルを開いてる人がいる)に失敗すると考えてますが
そういった行為はおこなっておらず、かつAdd-Contentコマンドを使ってイベントログを取得する周期は5分間(当然二重起動防止)なので、
Add-Contentコマンドが失敗する別要因を探しています。バグやこういった場合に失敗が考えられるといった情報が頂きたいです。
おねがいします!
回答
-
私も似たような現象に悩まされたことがありますが、そのときはインデックスサービスが割り込みをかけていたのが原因でした。
どうもAdd-Contentコマンドレットをループ内で利用する場合、たとえば
foreach($log in $logs){Add-Content test.exe $log}
のように記述した場合は、1回の反復で「ファイルをopenする→ファイルに追記する→ファイルをcloseする」という処理が走るようです。
そのため全体としてみるとファイルはロックされず、開いて閉じてが高速で繰り返されることになります。したがってファイルを閉じて再び開かれる隙をついて、インデックスサービスなどが割り込みをかけることが可能で、そういった場合に後続処理が失敗してしまいます。
対処法はいくつかあると思いますが、
$logs | Add-Content test.txt
のようにパイプライン経由で文字列配列なりコマンド出力なりをAdd-Contentコマンドレットに渡してやると、ファイルopen→1行目書き込み→2行目書き込み・・・→ファイルclose のように動作するようです。
ただしどうしてもループ内にファイル追記処理を書かなければならない状況もあるかと思います。その場合のいい解決法は私も探しているところですが、とりあえずは.NETのStreamWriterクラス等を使って、ちゃんとストリームを開いてそこに書き込むようにしています。そうするとファイルにロックがかかるので、途中で他から割り込みがかかる心配はなくなります。
- 回答としてマーク mokocyo 2013年4月17日 7:37
すべての返信
-
私も似たような現象に悩まされたことがありますが、そのときはインデックスサービスが割り込みをかけていたのが原因でした。
どうもAdd-Contentコマンドレットをループ内で利用する場合、たとえば
foreach($log in $logs){Add-Content test.exe $log}
のように記述した場合は、1回の反復で「ファイルをopenする→ファイルに追記する→ファイルをcloseする」という処理が走るようです。
そのため全体としてみるとファイルはロックされず、開いて閉じてが高速で繰り返されることになります。したがってファイルを閉じて再び開かれる隙をついて、インデックスサービスなどが割り込みをかけることが可能で、そういった場合に後続処理が失敗してしまいます。
対処法はいくつかあると思いますが、
$logs | Add-Content test.txt
のようにパイプライン経由で文字列配列なりコマンド出力なりをAdd-Contentコマンドレットに渡してやると、ファイルopen→1行目書き込み→2行目書き込み・・・→ファイルclose のように動作するようです。
ただしどうしてもループ内にファイル追記処理を書かなければならない状況もあるかと思います。その場合のいい解決法は私も探しているところですが、とりあえずは.NETのStreamWriterクラス等を使って、ちゃんとストリームを開いてそこに書き込むようにしています。そうするとファイルにロックがかかるので、途中で他から割り込みがかかる心配はなくなります。
- 回答としてマーク mokocyo 2013年4月17日 7:37