案件でbatファイルの修正を行った際に発覚した割とヤバい(と思う)挙動があったので記事にしました。
#はじめに
リダイレクトはコマンドの出力結果を書き込んでくれるので
batファイルの各コマンドの終わりに入れている人も多いと思いますし、それはごく自然な書き方だと思います。
このようにリダイレクト先のtxtはコマンドの結果ログとして使用することが出来ます。
標準エラー出力をリダイレクトするようにしとけば何かエラーあっても
ログ見ればエラー内容を特定できます。超便利ですね。
じゃあ何がまずいのか。。。
#問題点
リダイレクトに失敗するとリダイレクト元のコマンドが実行されないことが問題点です。
え?リダイレクトってコマンドの出力結果を書込みにいくんだから
順序はコマンド実行⇒出力結果書込みでしょ?コマンドは先に実行されてんじゃん。
・・・と思ってましたが現実は違いました。
#再現テスト
簡単に再現できるのでやってみましょう。
- 準備としてaaa.txtとbbb.txtを作成
- aaa.txtを排他モードでオープン
- del 直下のパス\bbb.txt >> 直下のパス\aaa.txt
- 「プロセスはファイルにアクセスできません。別のプロセスが使用中です。」というメッセージが出る
- 削除対象のbbb.txtは削除されていない
今回は一例としてリダイレクト元のコマンドをdelにしましたが別にコマンド自体はなんでもいいです。
コマンド実行有無を分かりやすくしたかっただけです。
#解決策
複数プロセスがリダイレクト先ファイルをオープンしに行かないように
リダイレクト先のファイルを処理ごとに分けるか、
リダイレクトが完了してから次処理に移る作り込みをするとかいろいろ考えられると思います。
後者は戻り値見たりする必要がありそうなのでちょっと大変そう。。。?
他にリダイレクトが失敗するケースは
そもそもファイルにアクセス権がないユーザ使ってる。とか
指定したパスが存在しない。とかがありますけど
それは処理ごとの単体テストでちゃんと確認しておけばいいのでは、と思います。
土台から変えるなら
・リダイレクトをやめちゃう。
・そもそもbatを使わない、VBやC等で動かす。
・そもそもWindowsを(ry)
とかでしょうか。