robocopy単体でも有用なツールなのですが、データのバックアップを運用するとなるとバックアップ失敗時にメールを送ってくれるようにしてもらうと楽になります。
一からスクリプト書くの面倒だなあと思ってググってたらrobocopy.exeを使ったWindows用バックアップスクリプト | kurimon.meにドンピシャなコードが載ってました。ブロガーさんに感謝です。
ほぼコピペですが、バックアップ対象を別ファイルに持たしてバッチファイルから取得し、robocopy実行後古いログファイルを削除するという場合のコードを載せておきます。
なお、robocopyからの戻り値はビットマスクとなるので、エラーと判断するのは、戻り値が8以上という判定にしたほうが良いかもしれません。
設定ファイル
robocopy_bkup_conf.txt に / 区切りでバックアップ元、バックアップ先、ログファイル名の設定を書きます。(ログファイルは途中までは共通とするためユニーク部分だけ記述)
以下のような感じです。
robocopy_bkup_conf.txt(/を区切り文字として バックアップ元、バックアップ先、ログファイル名 を設定) \\server01\share\user/D:\bkup\user/user.txt \\server02\nas\hoge/D:\bkup\hoge/hoeg.txt
バッチファイル
以下がタスクスケジューラに登録するバッチです。
設定ファイルよりバックアップ元、バックアップ先、ログファイル名を取得し、robocopyを実行するVBScriptを呼び出し後、古いログファイルを削除するVBScriptを呼び出します。
@echo off rem 日付を取得 set YYYYMMDD=%DATE:/=% rem コピー元、コピー先、ログファイル名の設定ファイル呼び出し FOR /F "tokens=1,2,3 delims=/" %%A IN (robocopy_bkup_conf.txt) DO ( rem VBスクリプトを実行 %%A:バックアップ元 %%B:バックアップ先 %%C:ログファイル名 cscript "robocopy.vbs" %%A %%B D:\diff\log\robocopyLog_%YYYYMMDD%_%%C ) rem 古いログファイル削除 cscript "LogOldFile_Del.vbs"
robocopyを実行するVBScript
実際のrobocopyコマンドを叩き、結果をメールで送信する部分のVBScriptです。
Option Explicit Dim objNetWork , objShell Dim strSubject '必要なオブジェクトをセット Set objNetWork = WScript.CreateObject("WScript.Network") 'ホスト名、ユーザ名の取得 Set objShell = CreateObject("WScript.Shell") 'ネットワークドライブのマウントとrobocopyコマンド 'robocopy.batから渡された引数をチェックし、正しく取得できなければエラーメールを送信して終了 If WScript.Arguments.Count <> 3 Then strSubject = "[Robocopy_BackupError][" & CStr(Now()) & "]" & objNetWork.UserName & "@" & objNetWork.ComputerName SendMail( strSubject , "Host:" & objNetWork.ComputerName & "のバックアップ処理に失敗しました" & vbCrLf & "Error:引数が不正です「robocopy.bat」を確認してください") End If '引数を取得 strLocalDir = WScript.Arguments.Item(0) 'コピー元ディレクトリ strRemoteDir = WScript.Arguments.Item(1) 'コピー先ディレクトリ strLogFile = WScript.Arguments.Item(2) 'ログファイル WScript.Echo strLocalDir WScript.Echo strRemoteDir 'robocopyがインストールされているか確認。robocopyを引数なしで実行しエラーとなるかどうかで、コマンドがあるかどうか判断。 On Error Resume Next strRobocopyStatus = objShell.Run("robocopy.exe ",7,True) If Err.Number <> 0 Then On Error Goto 0 strSubject = "[Robocopy_BackupError][" & CStr(Now()) & "]" & objNetWork.UserName & "@" & objNetWork.ComputerName SendMail( strSubject , "エラー:robocopyがインストールされていません。") WScript.Quit End If On Error Goto 0 'バックアップ(第二引数が7なのでウィンドウを最小化したまま。 /TEEオプション付けてるので進捗を表示します。コマンドプロンプト最小化しないと描画に時間取られるので最小化してます) 'strRobocopyStatus = objShell.Run("cmd /c robocopy.exe " & strLocalDir & " " & strRemoteDir & " " & " /E /COPYALL /R:2 /W:5 /FFT /TEE /NDL /NP /LOG:" & strLogFile ,7,True) 'ミラーバックアップの場合 strRobocopyStatus = objShell.Run("cmd /c robocopy.exe " & strLocalDir & " " & strRemoteDir & " " & " /MIR /COPYALL /R:2 /W:5 /FFT /NDL /NP /LOG:" & strLogFile ,7,True) Dim strMsg , strStatus ,iRobocopyStatus , strInfo iRobocopyStatus = CInt(strRobocopyStatus) strStatus = "------------------------------" & vbCrLf & "Status: " & vbCrLf strInfo = "バックアップ元:" & strLocalDir & vbCrLf & "バックアップ先:"& strRemoteDir & vbCrLf 'robocopyからの戻り値を論理積を取って詳細メッセージ生成 If (iRobocopyStatus AND 16) = 16 Then strStatus = strStatus & "***FATAL ERROR***" strMsg = strMsg & "Code16:重大なエラー。Robocopyは,ファイルをひとつもコピーしませんでした。これは,使用法の間違いか転送元または転送先ディレクトリへのアクセス権が不十分なために発生するエラーです。" & vbCrLf End If If (iRobocopyStatus AND 8) = 8 Then strStatus = strStatus & " FAIL " strMsg = strMsg & "Code8:いくつかのファイルまたはディレクトリがコピーできませんでした(コピーエラーが発生し,リトライ上限を上回りました)。以降のエラーをチェックしてください。" & vbCrLf End If If (iRobocopyStatus AND 4) = 4 Then strStatus = strStatus & " MISM " strMsg = strMsg & "Code4:いくつかMismatched(転送元のファイルと同名のディレクトリが転送先にある,あるいはその逆)ファイルまたはディレクトリがみつかりました。ログを調べてください。多分掃除が必要です。" & vbCrLf End If If (iRobocopyStatus AND 2) = 2 Then strStatus = strStatus & " XTRA " strMsg = strMsg & "Code2:いくつかのExtra(転送元に存在しないのに転送先に存在するファイル)ファイルまたはディレクトリがみつかりました。出力ログを調べてください。掃除が必要かもしれません。" & vbCrLf End If If (iRobocopyStatus AND 1) = 1 Then strStatus = strStatus & " COPY " strMsg = strMsg & "Code1:一つ以上のファイルが,うまくコピーされました(つまり新しいファイルは転送先に届きました)。" & vbCrLf End If If iRobocopyStatus = 0 Then strMsg = strMsg & "Code0:エラーは発生せず,コピーもされませんでした。転送元と転送先ディレクトリツリーは,完全に同期しています。" & vbCrLf End If strStatus = & vbCrLf & "---------------------------------" 'robocopyからの戻り値によって処理を振り分ける8以上が致命的なエラー If iRobocopyStatus >= 8 Then strSubject = "[Robocopy_BackupError][" & CStr(Now()) & "]" & objNetWork.UserName & "@" & objNetWork.ComputerName SendMail(strSubject , "Host:" & objNetWork.ComputerName & "のバックアップ処理に致命的なエラーが発生しました。ログファイルを確認してください。" & vbCrLf & _ vbCrLf & strStatus & vbCrLf & strInfo & vbCrLf & vbCrLf & "詳細情報:" & vbCrLf & strMsg ) Else strSubject = "[Robocopy_BackupLog][" & CStr(Now()) & "]" & objNetWork.UserName & "@" & objNetWork.ComputerName SendMail(strSubject , "Host:" & objNetWork.ComputerName & "のバックアップ処理正常に終了しました。" & vbCrLf & _ vbCrLf & strStatus & vbCrLf & strInfo & vbCrLf & vbCrLf & "詳細情報:" & vbCrLf & strMsg ) End If Set objNetWork = Nothing 'こういう分け方もできる(MSのドキュメントより) 'if strRobocopyStatus 16 echo ***FATAL ERROR*** & goto end 'if strRobocopyStatus 15 echo FAIL MISM XTRA COPY & goto end 'if strRobocopyStatus 14 echo FAIL MISM XTRA & goto end 'if strRobocopyStatus 13 echo FAIL MISM COPY & goto end 'if strRobocopyStatus 12 echo FAIL MISM & goto end 'if strRobocopyStatus 11 echo FAIL XTRA COPY & goto end 'if strRobocopyStatus 10 echo FAIL XTRA & goto end 'if strRobocopyStatus 9 echo FAIL COPY & goto end 'if strRobocopyStatus 8 echo FAIL & goto end 'if strRobocopyStatus 7 echo MISM XTRA COPY & goto end 'if strRobocopyStatus 6 echo MISM XTRA & goto end 'if strRobocopyStatus 5 echo MISM COPY & goto end 'if strRobocopyStatus 4 echo MISM & goto end 'if strRobocopyStatus 3 echo XTRA COPY & goto end 'if strRobocopyStatus 2 echo XTRA & goto end 'if strRobocopyStatus 1 echo COPY & goto end 'if strRobocopyStatus 0 echo --no change-- & goto end 'メール送信処理 Function SendMail(strSubject , strError) Dim strMailAddrTo , strSMTPServ , strMailAddrFrom , iSMTPPort '# メールアドレスを設定 strMailAddrTo = "to@hoge.example.com" strSMTPServ = "smtp.hoge.example.com" strMailAddrFrom = "from@hoge.example.com" iSMTPPort = 25 Dim objMail Set objMail = CreateObject("CDO.Message") 'メールを送信 objMail.From = strMailAddrFrom objMail.To = strMailAddrTo objMail.Subject = strSubject objMail.TextBody = strError objMail.Configuration.Fields.Item("http://schemas.microsoft.com/cdo/configuration/sendusing") = 2 objMail.Configuration.Fields.Item("http://schemas.microsoft.com/cdo/configuration/smtpserver") = strSMTPServ objMail.Configuration.Fields.Item("http://schemas.microsoft.com/cdo/configuration/smtpserverport") = iSMTPPort objMail.Configuration.Fields.Update objMail.Send Set objMail = Nothing End Function
古いログファイルを削除するVBScript
ログファイルが、D:\diff\log\robocopyLog_YYYYMMDD_設定名 で保存するようにしているので、だんだんとたまっていきます。
それで、指定日数経った D:\diff\log\ 配下の robocopyLog_ から始まるファイルを削除するVBScriptです。
'logファイルの格納されているフォルダーのパス Const cFolderPath = "D:\diff\log" '以下の文字列が先頭にあるファイルを削除する Dim strLogShareFile strLogShareFile = "robocopyLog_" '以下の日数経っているものを削除対象とする Dim iDate iDate=120 Dim fso, fl Dim tod, logDate, buf, diff Set fso = CreateObject("Scripting.FileSystemObject") tod = CDate(Split(Now, " ")(0)) For Each fl In fso.GetFolder(cFolderPath).Files ' strLogShareFileが先頭につくファイルのみ削除対象とする If InStr(1 , fl.Name , strLogShareFile , 1 ) = 1 Then buf = fso.GetFile(fl.Path).DateLastModified logDate = CDate(Split(buf, " ")(0)) diff = DateDiff("d", logDate, tod) If diff > iDate Then fl.Delete End If End If Next Set fso = Nothing
robocopyの戻り値ですが、リソースキット内のドキュメントによると以下のようになるようです。
Hex Bit Value Decimal Value Meaning If Set 0x10 16 Serious error. Robocopy did not copy any files. This is either a usage error or an error due to insufficient access privileges on the source or destination directories. 0x08 8 Some files or directories could not be copied (copy errors occurred and the retry limit was exceeded). Check these errors further. 0x04 4 Some Mismatched files or directories were detected. Examine the output log. Housekeeping is probably necessary. 0x02 2 Some Extra files or directories were detected. Examine the output log. Some housekeeping may be needed. 0x01 1 One or more files were copied successfully (that is, new files have arrived). 0x00 0 No errors occurred, and no copying was done. The source and destination directory trees are completely synchronized.
robocopy-j.docにはこの戻り値の日本語訳が書いてあったので、上記のスクリプトのエラー文字列も日本語表記にしています。
メール送信は汎用化できると思うので、別ファイルにしてしまったほうが良いかもしれません。