（我が家のPC運用）自作バッチでバックアップ

# 我が家のPCバックアップ

我が家にはWindows10デスクトップPCがあり、運用の1タスクとして定期的にバックアップを実施しています。

- システムのバックアップ：専用のアプリケーションで、アプリのスケジュール機能を使用して実施。
- データのバックアップ：自作バッチで、タスクスケジューラに登録し実施。

バッチを自作した理由は

- 実行の成否をテキストファイルに残したい。
- バックアップした差分ファイルを知りたい。
- 複数個所のデータバックアップを個別に実行したい、がそのパスを一元管理したい。
- 作業の妨げにならないよう、裏でひっそりと実行したい。

今回はこの自作バッチについて説明します。



# バッチの特徴

- 以下の4ファイルで構成します。ファイルは全てSJISで、全て同一場所に配置します。（※過去にUTF8としていましたが、何かと不便のためSJISに変更しました）
  - backupExec.bat（これは任意のファイル名でOK）
  - setenv.bat
  - backupMain.bat
  - backupSub.bat
- 実行するのはbackupExec.batです。このファイルは引数を指定してbackupMain.batを呼び出すのみです。  
  バックアップのタスク数に応じて複数用意します。  
  このファイルをタスクスケジューラに登録します。 
- backupMain.batは引数チェックやパスの存在チェックを実施した後、backupSub.batを呼び出します。
- バックアップはbackupSub.bat内のrobocopyコマンドで実行します。
- robocopyの結果をログファイルに出力します。
- バックアップの元先やログファイルパスをsetenv.batにまとめます。



# バッチのコード

## backupExec.bat

- 変数BASE_PATH：バッチファイルを格納しているパスを定義します。
- 「call backupMain.bat 211」の「211」がsetenv.bat内のバックアップポリシーと紐付きます。

```
@echo off

set BASE_PATH=C:\pcmaintenance\batch
cd %BASE_PATH%
call backupMain.bat 211

exit %EXIT_CODE_NORMAL%
```


## setenv.bat
- 変数SYNC_LOG_PATH：バックアップログファイルを格納するパスを定義します。
- 変数SYNC_FROM_PATH_211：バックアップ元のパスを定義します。  
  backupExec.batのパラメートを「211」としたので、SYNC_FROM_PATH_211が採用されます。
- 変数SYNC_TO_PATH_211：バックアップ先のパスを定義します。
- 変数SYNC_OPTION_211：robocopyのオプションが必要な場合に定義します。  
  下記のコードの場合、バックアップから除外するパスを指定しています。（ブラウザのキャッシュや、バックアップログファイル自身）
- 変数は211の他にも複数定義し、backupExec.batか別のバッチファイルから実行可能です。  
  下記のコードでは210というパラメータでもう一つのバックアップポリシーを定義し、backupExec.batとは別ファイル、別スケジュールで実施しています。

```
@echo off

set EXIT_CODE_NORMAL=0
set EXIT_CODE_ERROR=-1

set SYNC_LOG_PATH=D:\datas\log\backup
set SYNC_TO_BASE_PATH=E:\backup

rem ■低頻度バックアップ
set SYNC_FROM_PATH_211=D:
set SYNC_TO_PATH_211=%SYNC_TO_BASE_PATH%\低頻度バックアップ\システムデータ
set SYNC_OPTION_211=/xd "D:\datas\Chrome" /xd "D:\datas\log\backup"

rem ■高頻度バックアップ（ユーザ名はダミー）
set SYNC_FROM_PATH_210=C:\Users\user\デスクトップ
set SYNC_TO_PATH_210=%SYNC_TO_BASE_PATH%\高頻度バックアップ\デスクトップ

exit /b %EXIT_CODE_NORMAL%
```


## backupMain.bat
- バックアップ処理のメインです。  
  引数チェック、パスの存在チェックを実施した後、backupSub.batを呼び出します。
  
```
@echo off

rem ****************
rem バックアップ実行バッチ
rem 第１引数：バックアップ対象パスのINDEX（setenv.bat内に記述）
rem ****************

set MYSHELL_NAME=%0
echo [START]%MYSHELL_NAME%
echo [INFO]%date% %time%
echo [INFO]ユーザ名:%USERNAME%


rem ****************
rem 共通初期設定
rem ****************

cd /d %~dp0
call .\setenv.bat > nul 2>&1
if not %errorlevel% == 0 (
    echo [ERROR]setenvバッチ実行エラー
    echo [END]%MYSHELL_NAME%
    exit /b %EXIT_CODE_ERROR%
)


rem ****************
rem 同期パスの取得
rem ****************

rem パスの取得
set PATH_INDEX=%1
setlocal enabledelayedexpansion
    rem 引数のINDEXでパス変数名を形成
    set SYNC_FROM_PATH_NAME=SYNC_FROM_PATH_%PATH_INDEX%
    set SYNC_TO_PATH_NAME=SYNC_TO_PATH_%PATH_INDEX%
    set SYNC_OPTION_NAME=SYNC_OPTION_%PATH_INDEX%

    rem 形成した変数名の値を取得
    set SYNC_FROM_PATH_LOCAL=!%SYNC_FROM_PATH_NAME%!
    set SYNC_TO_PATH_LOCAL=!%SYNC_TO_PATH_NAME%!
    set SYNC_OPTION_LOCAL=!%SYNC_OPTION_NAME%!

rem ローカル変数を外部に適用するため、外部変数にセット
endlocal && set SYNC_FROM_PATH=%SYNC_FROM_PATH_LOCAL% && set SYNC_TO_PATH=%SYNC_TO_PATH_LOCAL% && set SYNC_OPTION=%SYNC_OPTION_LOCAL%

if "%SYNC_FROM_PATH%" == "" (
    echo [ERROR]SYNC_FROM_PATH未定義:引数=%PATH_INDEX%
    echo [END]%MYSHELL_NAME%
    echo ----
    echo ----
    exit /b %EXIT_CODE_ERROR%
)
if "%SYNC_TO_PATH%" == "" (
    echo [ERROR]SYNC_TO_PATH未定義:引数=%PATH_INDEX%
    echo [END]%MYSHELL_NAME%
    echo ----
    echo ----
    exit /b %EXIT_CODE_ERROR%
)

rem パスの存在チェック
if not exist "%SYNC_FROM_PATH%" (
    echo [ERROR]SYNC_FROM_PATH不正:%SYNC_FROM_PATH%
    echo [END]%MYSHELL_NAME%
    echo ----
    echo ----
    exit /b %EXIT_CODE_ERROR%
)
if not exist "%SYNC_TO_PATH%" (
    echo [ERROR]SYNC_TO_PATH不正:%SYNC_TO_PATH%
    echo [END]%MYSHELL_NAME%
    echo ----
    echo ----
    exit /b %EXIT_CODE_ERROR%
)


rem ****************
rem 同期実行
rem ****************

call .\backupSub.bat "%SYNC_FROM_PATH%" "%SYNC_TO_PATH%" "%SYNC_OPTION%"
if not %errorlevel% == 0 (
    echo [ERROR]同期失敗
    echo [END]%MYSHELL_NAME%
    exit /b %EXIT_CODE_ERROR%
)


echo [INFO]%date% %time%
echo [END]%MYSHELL_NAME%
echo ----
echo ----
exit /b %EXIT_CODE_NORMAL%
```

## backupSub.bat
- robocopyでバックアップします。オプションはコードの通りです。
- ログファイルはbackup_schedule_log_日付.txtです。

```
@echo off

rem ****************
rem バックアップ実行サブバッチ
rem 第１引数：バックアップ元パス
rem 第２引数：バックアップ先パス
rem 第３引数：オプション
rem ****************

rem ログファイル名の生成
set DATE_TMP=%date%
set LOG_SUFFIX=%DATE_TMP:~0,4%%DATE_TMP:~5,2%%DATE_TMP:~8,2%
set LOG_FILE_PATH=%SYNC_LOG_PATH%\backup_schedule_log_%LOG_SUFFIX%.txt

echo [INFO]同期元パス:%~1
echo [INFO]同期先パス:%~2
echo [INFO]オプション:%~3
echo [INFO]ログファイルパス:%LOG_FILE_PATH%

rem robocopyでバックアップ
set RB_CMD_PARAM=%~1 %~2 /mir /copy:DT /z /r:1 /w:1 /xjd /ipg:10 /fft /np /ndl /log+:%LOG_FILE_PATH% /xd "System Volume Information" %~3
echo robocopy %RB_CMD_PARAM%
robocopy %RB_CMD_PARAM%
attrib -H -S %~2

exit /b %EXIT_CODE_NORMAL%
```