ROBOCOPYのログからエラー内容とエラーになったファイル名だけ取り出したい時ってありませんか。
毎晩動かしているロボコピーがよくエラーを吐きます。コマンドの終了コードを判定して、正常に完了したかエラーが発生したかをメール通知しているので、エラーが発生した場合はログをつらつらと確認する必要があり、データ量(ファイル数)が多いので、毎回ログを見てエラーファイルを特定するだけでヘトヘトになります。この無限地獄から脱するためにエラー箇所を抜粋する方法を考えたので紹介します。我ながら結構使えると思ってます。
現状と変えたいコト
現状のバックアップスクリプトはRobocopyコマンドの終了コードをみて、正常終了なら正常にバックアップが完了したことをメール通知するようになっている。
反対に異常終了した場合は、Robocopyのログをメールに添付して送付するようになっている。
添付されているならそのまま確認できるじゃんと一瞬思うが、ファイル数が多くログのサイズが20MBくらいまでになる。個人宛に送るならそれでもいいがML宛に送っているので、これも問題。
だけどエラーが発生したときにわざわざサーバにログインしてログを確認するのも手間がかかる。共有フォルダに出力されるようにしたとしても数万行?くらいのログを確認するのは面倒。なので、ログから以下の2点を取り出したい。
- エラー内容
- バックアップできなかったファイル名
さらに、それをメールに記載して送りたい。が、それは一旦置いておいて、今回は、冒頭に書いた通り↑の2点を取り出すところの紹介です。
どういうふうにやるの?
ROBOCOPYのログの出力内容を確認
まずROBOCOPYのログの出力形式は、
バックアップに成功した場合は、行頭がタブかスペースだったかになっていて、その後にファイル名、フォルダ名が記録される。
逆に失敗した場合は行頭に年月日が出力され、その後にエラーコード、ファイル名・フォルダ名が記録され、その次の行にエラー内容が記録される。
1 2 |
2016/09/20 03:50:03 エラー 32 (0x00000020) ファイルをコピーしています \\192.168.10.100\d$\WSUS\DbFiles\SUSDB_log.ldf プロセスはファイルにアクセスできません。別のプロセスが使用中です。 |
なので、、、以下の2つができればよさそうだということがわかりました。
ポイント
- 行頭の"yyyy/mm/dd"を取る
- 行頭に"yyyy/mm/dd"がある次の行を取る
次は実際に取り出すコマンドです。
コマンド
Linuxでいうとgrepしてるだけなんだけど、powershellで書くとなんだか仰々しくみえるな。。。あと、いきなりSelect-Stringではじめると行頭にファイル名が入ってしまうので、Get-contentを使ってます。
1 |
Get-Content $ROBOCOPY_LOG | Select-String -pattern "^\d{4}/\d{2}/\d{2}" -Context 0,1 -Encoding default |
行頭の"yyyy/mm/dd"をとると、例えば ”9876/54/32” みたいな場合でも引っかかってしまう。。。まぁ年月日以外でスラッシュ入った8桁の数字なんてほぼ無いから大丈夫だと思うけど。
・・・きっちりやるならこんな感じか。2099年までは持つし。
1 |
Get-Content $ROBOCOPY_LOG | Select-String -pattern "^20\d{2}/(0?[1-9]|1[0-2])/(0?[1-9]|[12][0-9]|3[01])" -Context 0,1 -Encoding default |
次に、「行頭に"yyyy/mm/dd"がある次の行をとる」を実現するために「-Context」オプションを使い、引数に「前何行,後何行」を指定してやる。grepでいうところの「-B」と「-A」と同じですね。今回はgrepした"yyyy/mm/dd"の後1行が取れれば良いので「0,1」と指定する。
おまけ
以下のエントリでPowerShellを使ってGmail送信するスクリプトを紹介しているので、それを使って、抜粋したエラー内容をメール送信することもできます。