Guest User

Windows Differential Backup Script v1.4.7

a guest
Aug 5th, 2013
177
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. :: Purpose:       Rotating differential backup using 7-Zip for compression.
  2. :: Requirements:  - forfiles.exe from Microsoft
  3. ::                - 7-Zip
  4. :: Author:        vocatus on reddit.com/r/usefulscripts
  5. :: Version:       1.4.7 - Removed some redundant %TIME% stamps in the logs, under the Cleanup section
  6. ::                1.4.6 + Added two additional "help" flags: "-h" and "--help"
  7. ::                1.4.5 + Added better instructions for what variables can be set to
  8. ::                1.4.4 + Added quotes around variables that could contain spaces in a few places
  9. ::                    * Some comment cleanup, and some logging formatting cleanup.
  10. ::                1.4.3 / Tweaked logging to only display exclamation point if there was an error
  11. ::                    / Tweaked logging to display time correctly (no extra spaces)
  12. ::                1.4.2 / Some logging tweaks
  13. ::                1.4.1 / Some logging tweaks
  14. ::                1.4   + Added quotes around SOURCE variable that were missing in a couple places
  15. ::                1.3   * Fixed backup archiving - wasn't rotating properly on network paths. We use pushd to get around this
  16. ::                      - Added "-s" option to show job options that the script WOULD execute with
  17. ::                      - Major overhaul of code order and logic. Stuff should break less now.
  18. ::                      - Many fixes to exclusions file checking
  19. ::                1.2   - Fixed problem with cleaning backups. Now cleans staging area and long-term destination area.
  20. ::                        Normally an archive (-a) switch cleans the staging area, but now the -c switch does as well, just in case.
  21. ::                      - Also fixed issue with forfiles.exe not being able to read UNC paths. We use pushd to get around this.
  22. ::                        Pushd auto-assigns the next available drive letter to a UNC path, then discards it when we use popd.
  23. ::                1.1   - Added option to use an exclude file to specify files/folders to exclude from the backup
  24. ::                1.0b    Some tweaks to logging
  25. ::                1.0     Initial write
  26.  
  27. :: Notes:         My intention for this script was to keep the logic controlling schedules, backup type, etc out of the script and
  28. ::                let an invoking program handle it (e.g. Task Scheduler). You simply run this script with a flag to perform an action.
  29. ::                If you want to schedule monthly backups, purge old files, etc, just set up task scheduler jobs for those tasks,
  30. ::                where each job calls the script with a different flag.
  31.  
  32. :: Usage:         Run this script without any flags for a list of possible actions. Run it with a flag to perform that action.
  33. ::                Flags:
  34. ::                 -f   create full backup
  35. ::                 -d   create differential backup (full backup must already exist)
  36. ::                 -r   restore from a backup (extracts to your staging area)
  37. ::                 -a   archive (close out/rotate) the current backup set. This:
  38. ::                      1. moves all .7z files in the %DESTINATION% into a folder named with the current date
  39. ::                      2. deletes all .7z files from the staging area
  40. ::                 -c   clean up (delete) old backup sets from staging and destination. If you specify a number
  41. ::                      of days after the command it will run automatically without any confirmation. Be careful with this!
  42. ::                 -s   show job options (show what the variables are set to)
  43.  
  44. :: Important:     If you want to set this script up in Windows Task Scheduler, be aware that Task Scheduler
  45. ::                can't use mapped network drives (X:\, Z:\, etc) when it is set to "Run even if user isn't logged on."
  46. ::                The task will simply fail to do anything (because Scheduler can't see the drives). To work around this use
  47. ::                UNC paths instead (\\server\backup_folder etc) for your source, destination, and staging areas.
  48.  
  49. :: TODO:           
  50. ::                1. Add md5sum checksum file in the backup directory (md5sum each full and diff and store in a file)
  51.  
  52.  
  53. :: Prep
  54. @echo off
  55. SETLOCAL
  56. set VERSION=1.4.7
  57. set SCRIPT_NAME=%0%
  58.  
  59. :::::::::::::::
  60. :: VARIABLES ::
  61. :::::::::::::::
  62. :: Rules for variables:
  63. ::  * NO quotes!                       (bad:  "c:\directory\path"       )
  64. ::  * NO trailing slashes on the path! (bad:   c:\directory\            )
  65. ::  * Spaces are okay                  (okay:  c:\my folder\with spaces )
  66. ::  * Network paths are okay           (okay:  \\server\share name      )
  67. ::                                     (       \\172.16.1.5\share name  )
  68.  
  69. :: Specify the folder you want to back up here.
  70. set SOURCE=C:\Users\vocatus\SuperImportantDocuments
  71.  
  72. :: Work area where everything is stored while compressing. Should be a fast drive or something that can handle a lot of writes
  73. :: Recommend not using a network share unless it's Gigabit or faster.
  74. set STAGING=P:\backup_staging
  75.  
  76. :: This is the final, long-term destination for your backup after it is compressed.
  77. set DESTINATION=\\CoolServerName\backups\folder with spaces\SuperImportantDocuments
  78.  
  79. :: If you want to customize the prefix of the backup files, do so here. Don't use any special characters (like underscores)
  80. :: The script automatically suffixes an underscore to this name. Recommend not changing this unless you really need to.
  81. ::  * Spaces are NOT OKAY to use here!
  82. set BACKUP_PREFIX=backup
  83.  
  84. :: OPTIONAL: If you want to exclude some files or folders, you can specify your exclude file here. The exclude file is a list of
  85. :: files or folders (wildcards in the form of * are allowed and recommended) to exclude.
  86. :: If you specify a file here and the script can't find it, it will abort.
  87. :: If you leave this blank, the script won't ignore any files.
  88. set EXCLUSIONS_FILE=C:\Users\vocatus\Scripts\backup_differential_excludes.txt
  89.  
  90. :: Log settings. Max size is how big (in bytes) the log can be before it is archived. 1048576 bytes is one megabyte
  91. set LOGPATH=%SystemDrive%\Logs
  92. set LOGFILE=%COMPUTERNAME%_%BACKUP_PREFIX%_differential.log
  93. set LOG_MAX_SIZE=104857600
  94.  
  95. :: Location of 7-Zip and forfiles.exe
  96. set SEVENZIP="C:\Program Files\7-Zip\7z.exe"
  97. set FORFILES=%WINDIR%\system32\forfiles.exe
  98.  
  99. :: Don't touch anything below this line. If you do, you will break something.
  100. set CUR_DATE=%DATE:~-4%-%DATE:~4,2%-%DATE:~7,2%
  101. set JOB_TYPE=%1
  102. set JOB_ERROR=0
  103. set DAYS=%2
  104. set RESTORE_TYPE=NUL
  105.  
  106.  
  107. ::::::::::::::::::::::::::::
  108. :: JOB TYPE DETERMINATION ::
  109. ::::::::::::::::::::::::::::
  110. :job_type_determination
  111. if '%JOB_TYPE%'=='' set JOB_TYPE=help
  112. if '%JOB_TYPE%'=='/?' set JOB_TYPE=help
  113. if '%JOB_TYPE%'=='-?' set JOB_TYPE=help
  114. if '%JOB_TYPE%'=='-h' set JOB_TYPE=help
  115. if '%JOB_TYPE%'=='--help' set JOB_TYPE=help
  116. if /i '%1'=='/f' set JOB_TYPE=full
  117. if /i '%1'=='-f' set JOB_TYPE=full
  118. if /i '%1'=='/d' set JOB_TYPE=differential
  119. if /i '%1'=='-d' set JOB_TYPE=differential
  120. if /i '%1'=='/r' set JOB_TYPE=restore
  121. if /i '%1'=='-r' set JOB_TYPE=restore
  122. if /i '%1'=='/a' set JOB_TYPE=archive_backup_set
  123. if /i '%1'=='-a' set JOB_TYPE=archive_backup_set
  124. if /i '%1'=='/c' set JOB_TYPE=cleanup_archives
  125. if /i '%1'=='-c' set JOB_TYPE=cleanup_archives
  126. if /i '%1'=='/s' goto show_options
  127. if /i '%1'=='-s' goto show_options
  128. :: If none of the above were specified then show the help screen
  129. if %JOB_TYPE%==help (
  130.     echo.
  131.     echo   %SCRIPT_NAME% v%VERSION%
  132.     echo.
  133.     echo   Usage: %SCRIPT_NAME% ^< -f ^| -d ^| -r ^| -a ^| -c ^[days^] ^>
  134.     echo.
  135.     echo   Flags:
  136.     echo    -f:  create a full backup
  137.     echo    -d:  create a differential backup ^(requires an existing full backup^)
  138.     echo    -r:  restore from a backup ^(extracts to %STAGING%\%BACKUP_PREFIX%_restore^)
  139.     echo    -a:  archive the current backup set. This will:
  140.     echo           1. move all .7z files located in:
  141.     echo              %DESTINATION%
  142.     echo              into a dated archive folder.
  143.     echo           2. purge ^(delete^) all copies in the staging area ^(%STAGING%^)
  144.     echo    -c:  clean ^(AKA delete^) archived backup sets from staging and long-term storage.
  145.     echo         Optionally specify number of days to run automatically. Be careful with this!
  146.     echo         Note that this requires a previously-archived backup set ^(-a option^)
  147.     echo    -s:  show job options ^(show what parameters the script WOULD execute with^)
  148.     echo.
  149.     echo   Edit this script before running it to specify your source, destination, and work directories.
  150.     goto end
  151.     )
  152.  
  153.  
  154. :::::::::::::::::::::::
  155. :: LOG FILE HANDLING ::
  156. :::::::::::::::::::::::
  157. :log
  158. :: Make the logfile if it doesn't exist
  159. if not exist %LOGPATH% mkdir %LOGPATH%
  160. if not exist %LOGPATH%\%LOGFILE% echo. > %LOGPATH%\%LOGFILE%
  161.  
  162. :: Check log size. If it's less than our max, then go ahead and get started
  163. for %%R in (%LOGPATH%\%LOGFILE%) do if %%~zR LSS %LOG_MAX_SIZE% goto required_files_check
  164.  
  165. :: If the log was too big, go ahead and rotate it.
  166. pushd %LOGPATH% 2>&1
  167. del /F %LOGFILE%.ancient 2>NUL
  168. rename %LOGFILE%.oldest %LOGFILE%.ancient 2>NUL
  169. rename %LOGFILE%.older %LOGFILE%.oldest 2>NUL
  170. rename %LOGFILE%.old %LOGFILE%.older 2>NUL
  171. rename %LOGFILE% %LOGFILE%.old 2>NUL
  172. popd
  173.  
  174.  
  175. ::::::::::::::::::::::::::
  176. :: REQUIRED FILES CHECK ::
  177. ::::::::::::::::::::::::::
  178. :required_files_check
  179. :: Make sure we can find 7-Zip
  180. IF NOT EXIST %SEVENZIP% (
  181.         echo %TIME%   ERROR: Couldn't find 7z.exe when script was invoked.>> %LOGPATH%\%LOGFILE%
  182.         cls
  183.         color 0c
  184.         echo.
  185.         echo  ERROR:
  186.         echo.
  187.         echo  Cannot find 7z.exe. You must edit this script
  188.         echo  and specify the location of 7-Zip before continuing.
  189.         echo.
  190.         echo  Script tried to find it here:
  191.         echo  %SEVENZIP%
  192.         echo.
  193.         pause
  194.         color
  195.         cls
  196.         goto end
  197.         )
  198. :: Make sure we can find forfiles.exe
  199. IF NOT EXIST %FORFILES% (
  200.         echo %TIME%   ERROR: Couldn't find forfiles.exe when script was invoked.>> %LOGPATH%\%LOGFILE%
  201.         cls
  202.         color 0c
  203.         echo.
  204.         echo  ERROR:
  205.         echo.
  206.         echo  Cannot find forfiles.exe. You must edit this script
  207.         echo  and specify the location of forfiles.exe before continuing.
  208.         echo.
  209.         echo  Script tried to find it here:
  210.         echo  %FORFILES%
  211.         echo.
  212.         pause
  213.         color
  214.         cls
  215.         goto end
  216.         )
  217.  
  218.  
  219. ::::::::::::::::::::
  220. :: DECISION POINT ::
  221. ::::::::::::::::::::
  222. :decision_point
  223. if '%JOB_TYPE%'=='full' goto %JOB_TYPE%
  224. if '%JOB_TYPE%'=='differential' goto %JOB_TYPE%
  225. if '%JOB_TYPE%'=='restore' goto %JOB_TYPE%
  226. if '%JOB_TYPE%'=='archive_backup_set' goto %JOB_TYPE%
  227. if '%JOB_TYPE%'=='cleanup_archives' goto %JOB_TYPE%
  228. goto end
  229.  
  230.  
  231. ::::::::::::::::::::::
  232. :: SHOW JOB OPTIONS ::
  233. ::::::::::::::::::::::
  234. :show_options
  235. echo.
  236. echo  Current configuration:
  237. echo.
  238. echo   Script Version:       %VERSION%
  239. echo   Source:               %SOURCE%
  240. echo   Destination:          %DESTINATION%
  241. echo   Staging area:         %STAGING%
  242. echo   Exclusions file:      %EXCLUSIONS_FILE%
  243. echo   Backup prefix:        %BACKUP_PREFIX%
  244. echo   Restores unpacked to: %STAGING%\%BACKUP_PREFIX%_restore
  245. echo   Log file:             %LOGPATH%\%LOGFILE%
  246. echo   Log max size:         %LOG_MAX_SIZE% bytes
  247. echo.
  248. echo  Edit this script with a text editor to customize these options.
  249. echo.
  250. goto end
  251.  
  252.  
  253. ::::::::::::::::::::::::
  254. :: CREATE FULL BACKUP ::
  255. ::::::::::::::::::::::::
  256. :full
  257. :: Check for an exclude file and make sure it exists.
  258. if '%EXCLUSIONS_FILE%'=='' goto full_go
  259. IF NOT EXIST %EXCLUSIONS_FILE% (
  260.         echo.
  261.         echo %TIME%   ERROR: An exclusions file was specified but couldn't be found:>> %LOGPATH%\%LOGFILE%
  262.         echo                %EXCLUSIONS_FILE%>> %LOGPATH%\%LOGFILE%
  263.         echo %TIME%   ERROR: An exclusions file was specified but couldn't be found:
  264.         echo                %EXCLUSIONS_FILE%
  265.         goto end
  266.         )
  267. :full_go
  268. echo.
  269. echo.>> %LOGPATH%\%LOGFILE%
  270. echo --------------------------------------------------------------------------------------------------->> %LOGPATH%\%LOGFILE%
  271. echo  Differential Backup Script v%VERSION% - initialized %CUR_DATE% at%TIME% by %USERDOMAIN%\%USERNAME%>> %LOGPATH%\%LOGFILE%
  272. echo.>> %LOGPATH%\%LOGFILE%
  273. echo  Script location:  %~dp0\%SCRIPT_NAME%>> %LOGPATH%\%LOGFILE%
  274. echo.>> %LOGPATH%\%LOGFILE%
  275. echo  Job Options>> %LOGPATH%\%LOGFILE%
  276. echo   Job type:        Full backup>> %LOGPATH%\%LOGFILE%
  277. echo   Source:          %SOURCE%>> %LOGPATH%\%LOGFILE%
  278. echo   Destination:     %DESTINATION%>> %LOGPATH%\%LOGFILE%
  279. echo   Staging area:    %STAGING%>> %LOGPATH%\%LOGFILE%
  280. echo   Exclusions file: %EXCLUSIONS_FILE%>> %LOGPATH%\%LOGFILE%
  281. echo   Backup prefix:   %BACKUP_PREFIX%>> %LOGPATH%\%LOGFILE%
  282. echo   Log location:    %LOGPATH%\%LOGFILE%>> %LOGPATH%\%LOGFILE%
  283. echo   Log max size:    %LOG_MAX_SIZE% bytes>> %LOGPATH%\%LOGFILE%
  284. echo --------------------------------------------------------------------------------------------------->> %LOGPATH%\%LOGFILE%
  285. echo.>> %LOGPATH%\%LOGFILE%
  286. echo %TIME%   Performing full backup of %SOURCE%...>> %LOGPATH%\%LOGFILE%
  287. echo %TIME%   Performing full backup of %SOURCE%...
  288.  
  289. :: Build archive
  290. echo.
  291. echo %TIME%   Building archive in staging area %STAGING%...>> %LOGPATH%\%LOGFILE%
  292. echo %TIME%   Building archive in staging area %STAGING%...
  293. echo.>> %LOGPATH%\%LOGFILE%
  294. echo ------- [ Beginning of 7zip output ] ------->> %LOGPATH%\%LOGFILE% 2>&1
  295. if not '%EXCLUSIONS_FILE%'=='' %SEVENZIP% a "%STAGING%\%BACKUP_PREFIX%_full.7z" "%SOURCE%" -xr@"%EXCLUSIONS_FILE%" >> %LOGPATH%\%LOGFILE%
  296. if '%EXCLUSIONS_FILE%'=='' %SEVENZIP% a "%STAGING%\%BACKUP_PREFIX%_full.7z" "%SOURCE%" >> %LOGPATH%\%LOGFILE%
  297. echo ------- [    End of 7zip output    ] ------->> %LOGPATH%\%LOGFILE% 2>&1
  298. echo.>> %LOGPATH%\%LOGFILE%
  299. echo.
  300.  
  301. :: Report on the build
  302. if %ERRORLEVEL%==0 (
  303.         echo %TIME%   Archive built successfully.>> %LOGPATH%\%LOGFILE%
  304.         echo %TIME%   Archive built successfully.
  305.         )
  306. if not %ERRORLEVEL%==0 (
  307.         set JOB_ERROR=1
  308.         echo %TIME% ! Archive built with errors.>> %LOGPATH%\%LOGFILE%
  309.         echo %TIME% ! Archive built with errors.
  310.         )
  311. :: Upload to destination
  312. echo.
  313. echo %TIME%   Uploading %BACKUP_PREFIX%_full.7z to %DESTINATION%...>> %LOGPATH%\%LOGFILE%
  314. echo %TIME%   Uploading %BACKUP_PREFIX%_full.7z to %DESTINATION%...
  315. echo.
  316. echo.>> %LOGPATH%\%LOGFILE%
  317. xcopy "%STAGING%\%BACKUP_PREFIX%_full.7z" "%DESTINATION%\" /Q /J /Y /Z >> %LOGPATH%\%LOGFILE%
  318. echo.>> %LOGPATH%\%LOGFILE%
  319.  
  320. :: Report on the upload
  321. if %ERRORLEVEL%==0 (
  322.         echo %TIME%   Uploaded full backup to '%DESTINATION%' successfully.>> %LOGPATH%\%LOGFILE%
  323.         echo %TIME%   Uploaded full backup to '%DESTINATION%' successfully.
  324.         ) ELSE (
  325.         set JOB_ERROR=1
  326.         echo %TIME% ! Upload of full backup to '%DESTINATION%' failed.>> %LOGPATH%\%LOGFILE%
  327.         echo %TIME% ! Upload of full backup to '%DESTINATION%' failed.
  328.         )
  329.  
  330. goto done
  331.  
  332.  
  333. ::::::::::::::::::::::::::::::::
  334. :: CREATE DIFFERENTIAL BACKUP ::
  335. ::::::::::::::::::::::::::::::::
  336. :differential
  337. :: Check for an exclude file and make sure it exists.
  338. if '%EXCLUSIONS_FILE%'=='' goto differential_go
  339. IF NOT EXIST %EXCLUSIONS_FILE% (
  340.         echo %TIME%   An exclusions file was specified but couldn't be found. Aborting.>> %LOGPATH%\%LOGFILE%
  341.         echo           Looked here: %EXCLUSIONS_FILE%>> %LOGPATH%\%LOGFILE%
  342.         echo %TIME%   An exclusions file was specified but couldn't be found. Aborting.
  343.         echo           Looked here: %EXCLUSIONS_FILE%
  344.         goto end
  345.         )
  346. :differential_go
  347. echo.>> %LOGPATH%\%LOGFILE%
  348. echo --------------------------------------------------------------------------------------------------->> %LOGPATH%\%LOGFILE%
  349. echo  Differential Backup Script v%VERSION% - initialized %CUR_DATE% at%TIME% by %USERDOMAIN%\%USERNAME%>> %LOGPATH%\%LOGFILE%
  350. echo.>> %LOGPATH%\%LOGFILE%
  351. echo  Script location:  %SCRIPT_NAME%>> %LOGPATH%\%LOGFILE%
  352. echo.>> %LOGPATH%\%LOGFILE%
  353. echo  Job Options>> %LOGPATH%\%LOGFILE%
  354. echo   Job type:        Differential backup>> %LOGPATH%\%LOGFILE%
  355. echo   Source:          %SOURCE%>> %LOGPATH%\%LOGFILE%
  356. echo   Destination:     %DESTINATION%>> %LOGPATH%\%LOGFILE%
  357. echo   Staging area:    %STAGING%>> %LOGPATH%\%LOGFILE%
  358. echo   Exclusions file: %EXCLUSIONS_FILE%>> %LOGPATH%\%LOGFILE%
  359. echo   Backup prefix:   %BACKUP_PREFIX%>> %LOGPATH%\%LOGFILE%
  360. echo   Log location:    %LOGPATH%\%LOGFILE%>> %LOGPATH%\%LOGFILE%
  361. echo   Log max size:    %LOG_MAX_SIZE% bytes>> %LOGPATH%\%LOGFILE%
  362. echo --------------------------------------------------------------------------------------------------->> %LOGPATH%\%LOGFILE%
  363. echo.>> %LOGPATH%\%LOGFILE%
  364. echo.
  365. :: Check for full backup existence
  366. if not exist "%STAGING%\%BACKUP_PREFIX%_full.7z" (
  367.         set JOB_ERROR=1
  368.         echo %TIME% ! ERROR: Couldn't find full backup file ^(%BACKUP_PREFIX%_full.7z^). You must create a full backup before a differential can be created.>> %LOGPATH%\%LOGFILE%
  369.         echo %TIME% ! ERROR: Couldn't find full backup file ^(%BACKUP_PREFIX%_full.7z^). You must create a full backup before a differential can be created.
  370.         goto end
  371.         ) ELSE (
  372.         :: Backup existed, so go ahead
  373.         echo %TIME%   Performing differential backup of %SOURCE%...>> %LOGPATH%\%LOGFILE%
  374.         echo %TIME%   Performing differential backup of %SOURCE%...
  375.         )
  376.        
  377. :: Build archive
  378. :differential_build
  379. echo.
  380. echo %TIME%   Building archive in staging area %STAGING%...>> %LOGPATH%\%LOGFILE%
  381. echo %TIME%   Building archive in staging area %STAGING%...
  382. echo.>> %LOGPATH%\%LOGFILE%
  383. echo ------- [ Beginning of 7zip output ] ------->> %LOGPATH%\%LOGFILE% 2>&1
  384. if not '%EXCLUSIONS_FILE%'=='' %SEVENZIP% u "%STAGING%\%BACKUP_PREFIX%_full.7z" "%SOURCE%" -ms=off -mx=9 -xr@"%EXCLUSIONS_FILE%" -t7z -u- -up0q3r2x2y2z0w2!"%STAGING%\%BACKUP_PREFIX%_differential_%CUR_DATE%.7z" >> %LOGPATH%\%LOGFILE% 2>&1
  385. if '%EXCLUSIONS_FILE%'=='' %SEVENZIP% u "%STAGING%\%BACKUP_PREFIX%_full.7z" "%SOURCE%" -ms=off -mx=9 -t7z -u- -up0q3r2x2y2z0w2!"%STAGING%\%BACKUP_PREFIX%_differential_%CUR_DATE%.7z" >> %LOGPATH%\%LOGFILE% 2>&1
  386. echo ------- [    End of 7zip output    ] ------->> %LOGPATH%\%LOGFILE% 2>&1
  387. echo.>> %LOGPATH%\%LOGFILE%
  388. echo.
  389. :: Report on the build
  390. if %ERRORLEVEL%==0 (
  391.         echo %TIME%   Archive built successfully.>> %LOGPATH%\%LOGFILE%
  392.         echo %TIME%   Archive built successfully.
  393.         )
  394. if not %ERRORLEVEL%==0 (
  395.         set JOB_ERROR=1
  396.         echo %TIME% ! Archive built with errors.>> %LOGPATH%\%LOGFILE%
  397.         echo %TIME% ! Archive built with errors.
  398.         )
  399.  
  400.  
  401. :: Upload to destination
  402. echo.
  403. echo %TIME%   Uploading %BACKUP_PREFIX%_differential_%CUR_DATE%.7z to %DESTINATION%... >> %LOGPATH%\%LOGFILE%
  404. echo %TIME%   Uploading %BACKUP_PREFIX%_differential_%CUR_DATE%.7z to %DESTINATION%...
  405. echo.>> %LOGPATH%\%LOGFILE%
  406. xcopy "%STAGING%\%BACKUP_PREFIX%_differential_%CUR_DATE%.7z" "%DESTINATION%\" /Q /J /Y /Z >> %LOGPATH%\%LOGFILE%
  407. echo.>> %LOGPATH%\%LOGFILE%
  408. :: Report on the upload
  409. if %ERRORLEVEL%==0 (
  410.         echo %TIME%   Uploaded differential file successfully.>> %LOGPATH%\%LOGFILE%
  411.         echo %TIME%   Uploaded differential file successfully.
  412.         )
  413.  
  414. if not %ERRORLEVEL%==0 (
  415.         set JOB_ERROR=1
  416.         echo %TIME% ! Upload of differential file failed.>> %LOGPATH%\%LOGFILE%
  417.         echo %TIME% ! Upload of differential file failed.
  418.         )
  419.  
  420. goto done
  421.  
  422.  
  423. :::::::::::::::::::::::::::
  424. :: RESTORE FROM A BACKUP ::
  425. :::::::::::::::::::::::::::
  426. :restore
  427. echo.
  428. echo  Restoring from a backup set.
  429. echo.
  430. echo   These backups are available:
  431. echo.
  432. dir /B /A:-D "%STAGING%" 2>NUL
  433. echo.
  434. echo  Enter the filename to restore from exactly as it appears above.
  435. echo  ^(Note: archived backup sets are not shown^)
  436. echo.
  437. :restore_menu
  438. set BACKUP_FILE=
  439. set /p BACKUP_FILE=Filename:
  440. if %BACKUP_FILE%==exit goto end
  441. echo.
  442. :: Make sure user didn't fat-finger the file name
  443. if not exist "%STAGING%\%BACKUP_FILE%" (
  444.         echo  ! ERROR: That file wasn^'t found. Check your typing and try again. && echo. && goto restore_menu
  445.         goto restore_menu
  446.         )
  447.  
  448. set CHOICE=y
  449. echo  ! Selected file '%BACKUP_FILE%'
  450. echo.
  451. set /p CHOICE=Is this correct [y]?:
  452.     if not %CHOICE%==y echo  Going back to menu... && goto restore_menu
  453. echo.
  454. echo  Great. Press any key to get started.
  455. pause >NUL
  456. echo  ! Starting restoration at%TIME% on %CUR_DATE%
  457. echo    This might take a while, be patient...
  458.  
  459. :: Test if we're doing a full or differential restore.
  460. if %BACKUP_FILE%==%BACKUP_PREFIX%_full.7z set RESTORE_TYPE=full
  461. if not %BACKUP_FILE%==%BACKUP_PREFIX%_full.7z set RESTORE_TYPE=differential
  462.  
  463.  
  464. :restore_go
  465. echo.>> %LOGPATH%\%LOGFILE%
  466. echo --------------------------------------------------------------------------------------------------->> %LOGPATH%\%LOGFILE%
  467. echo  Differential Backup Script v%VERSION% - initialized %CUR_DATE% at%TIME% by %USERDOMAIN%\%USERNAME%>> %LOGPATH%\%LOGFILE%
  468. echo.>> %LOGPATH%\%LOGFILE%
  469. echo  Script location:  %SCRIPT_NAME%>> %LOGPATH%\%LOGFILE%
  470. echo.>> %LOGPATH%\%LOGFILE%
  471. echo  Job Options>> %LOGPATH%\%LOGFILE%
  472. echo   Job type:        %RESTORE_TYPE% restore>> %LOGPATH%\%LOGFILE%
  473. echo   Source:          %STAGING%\%BACKUP_PREFIX%_full.7z>> %LOGPATH%\%LOGFILE%
  474. echo   Destination:     %STAGING%\%BACKUP_PREFIX%\>> %LOGPATH%\%LOGFILE%
  475. echo   Staging area:    %STAGING%>> %LOGPATH%\%LOGFILE%
  476. echo   Exclusions file: %EXCLUSIONS_FILE%>> %LOGPATH%\%LOGFILE%
  477. echo   Backup prefix:   %BACKUP_PREFIX%>> %LOGPATH%\%LOGFILE%
  478. echo   Log location:    %LOGPATH%\%LOGFILE%>> %LOGPATH%\%LOGFILE%
  479. echo   Log max size:    %LOG_MAX_SIZE% bytes>> %LOGPATH%\%LOGFILE%
  480. echo --------------------------------------------------------------------------------------------------->> %LOGPATH%\%LOGFILE%
  481. echo.
  482. :: Detect our backup type and inform the user
  483. if %RESTORE_TYPE%==differential (
  484.         echo %TIME%   Restoring from differential backup. Will unpack full backup then differential.>> %LOGPATH%\%LOGFILE%
  485.         echo %TIME%   Restoring from differential backup. Will unpack full backup then differential.
  486.         )
  487. if %RESTORE_TYPE%==full (
  488.         echo %TIME%   Restoring from full backup.>> %LOGPATH%\%LOGFILE%
  489.         echo %TIME%   Restoring from full backup.
  490.         echo %TIME%   Unpacking full backup...>> %LOGPATH%\%LOGFILE%
  491.         echo %TIME%   Unpacking full backup...
  492.         )
  493.  
  494. :: Start the restoration
  495. echo.>> %LOGPATH%\%LOGFILE%
  496. echo.
  497. echo ------- [ Beginning of 7zip output ] ------->> %LOGPATH%\%LOGFILE% 2>&1
  498. %SEVENZIP% x "%STAGING%\%BACKUP_PREFIX%_full.7z" -y -o"%STAGING%\%BACKUP_PREFIX%_restore\">> %LOGPATH%\%LOGFILE% 2>&1
  499. echo ------- [    End of 7zip output    ] ------->> %LOGPATH%\%LOGFILE% 2>&1
  500. :: Report on the unpack
  501. if %ERRORLEVEL%==0 (
  502.         echo %TIME%   Full backup unpacked successfully.>> %LOGPATH%\%LOGFILE%
  503.         echo %TIME%   Full backup unpacked successfully.
  504.         )
  505. if not %ERRORLEVEL%==0 (
  506.         set JOB_ERROR=1
  507.         echo %TIME% ! Full backup unpacked with errors.>> %LOGPATH%\%LOGFILE%
  508.         echo %TIME% ! Full backup unpacked with errors.
  509.         )
  510. :: If we're just doing a full restore (no differential), then go to the end
  511. if %RESTORE_TYPE%==full goto done
  512.        
  513. :: Now we unpack our differential file
  514. echo.
  515. echo %TIME%   Unpacking differential file %BACKUP_FILE%...>> %LOGPATH%\%LOGFILE%
  516. echo %TIME%   Unpacking differential file %BACKUP_FILE%...
  517. echo.>> %LOGPATH%\%LOGFILE%
  518. echo ------- [ Beginning of 7zip output ] ------->> %LOGPATH%\%LOGFILE% 2>&1
  519. %SEVENZIP% x "%STAGING%\%BACKUP_FILE%" -aoa -y -o"%STAGING%\%BACKUP_PREFIX%_restore\">> %LOGPATH%\%LOGFILE% 2>&1
  520. echo ------- [    End of 7zip output    ] ------->> %LOGPATH%\%LOGFILE% 2>&1
  521. echo.
  522. :: Report on the unpack
  523. if %ERRORLEVEL%==0 (
  524.         echo %TIME%   Differential file unpacked successfully.>> %LOGPATH%\%LOGFILE%
  525.         echo %TIME%   Differential file unpacked successfully.
  526.         ) ELSE (
  527.         :: Something broke!
  528.         set JOB_ERROR=1
  529.         echo %TIME% ! Differential file unpacked with errors.>> %LOGPATH%\%LOGFILE%
  530.         echo %TIME% ! Differential file unpacked with errors.
  531.         )
  532. goto done
  533.  
  534.  
  535. ::::::::::::::::::::::::
  536. :: ARCHIVE BACKUP SET :: aka rotate backups
  537. ::::::::::::::::::::::::
  538. :archive_backup_set
  539. echo.>> %LOGPATH%\%LOGFILE%
  540. echo --------------------------------------------------------------------------------------------------->> %LOGPATH%\%LOGFILE%
  541. echo  Differential Backup Script v%VERSION% - initialized %CUR_DATE% at%TIME% by %USERDOMAIN%\%USERNAME%>> %LOGPATH%\%LOGFILE%
  542. echo.>> %LOGPATH%\%LOGFILE%
  543. echo  Script location:  %SCRIPT_NAME%>> %LOGPATH%\%LOGFILE%
  544. echo.>> %LOGPATH%\%LOGFILE%
  545. echo  Job Options>> %LOGPATH%\%LOGFILE%
  546. echo   Job type:        Archive/rotate backup set>> %LOGPATH%\%LOGFILE%
  547. echo   Source:          %SOURCE%>> %LOGPATH%\%LOGFILE%
  548. echo   Destination:     %DESTINATION%>> %LOGPATH%\%LOGFILE%
  549. echo   Staging area:    %STAGING%>> %LOGPATH%\%LOGFILE%
  550. echo   Exclusions file: %EXCLUSIONS_FILE%>> %LOGPATH%\%LOGFILE%
  551. echo   Backup prefix:   %BACKUP_PREFIX%>> %LOGPATH%\%LOGFILE%
  552. echo   Log location:    %LOGPATH%\%LOGFILE%>> %LOGPATH%\%LOGFILE%
  553. echo   Log max size:    %LOG_MAX_SIZE% bytes>> %LOGPATH%\%LOGFILE%
  554. echo --------------------------------------------------------------------------------------------------->> %LOGPATH%\%LOGFILE%
  555. echo.>> %LOGPATH%\%LOGFILE%
  556. echo %TIME%   Archiving current backup set to %DESTINATION%\%CUR_DATE%_%BACKUP_PREFIX%_set.>> %LOGPATH%\%LOGFILE%
  557. echo %TIME%   Archiving current backup set to %DESTINATION%\%CUR_DATE%_%BACKUP_PREFIX%_set.
  558. :: Final destination: Make directory, move files
  559. pushd "%DESTINATION%"
  560. mkdir %CUR_DATE%_%BACKUP_PREFIX%_set >> %LOGPATH%\%LOGFILE%
  561. move /Y *.* %CUR_DATE%_%BACKUP_PREFIX%_set >> %LOGPATH%\%LOGFILE%
  562. popd
  563. echo.
  564. echo %TIME%   Deleting all copies in the staging area...>> %LOGPATH%\%LOGFILE%
  565. echo %TIME%   Deleting all copies in the staging area...
  566. :: Staging area: Delete old files
  567. del /Q /F "%STAGING%\*.7z">> %LOGPATH%\%LOGFILE%
  568. echo.>> %LOGPATH%\%LOGFILE%
  569. echo.
  570.  
  571. :: Report
  572. echo.>> %LOGPATH%\%LOGFILE%
  573. echo %TIME%   Backup set archived. All unarchived files in staging area were deleted.>> %LOGPATH%\%LOGFILE%
  574. echo %TIME%   Backup set archived. All unarchived files in staging area were deleted.
  575. echo.>> %LOGPATH%\%LOGFILE%
  576. goto done
  577.  
  578.  
  579. :::::::::::::::::::::::::::::::::::
  580. :: CLEAN UP ARCHIVED BACKUP SETS :: aka delete old sets
  581. :::::::::::::::::::::::::::::::::::
  582. :cleanup_archives
  583. IF NOT '%DAYS%'=='' goto cleanup_archives_go
  584.  
  585. :: List the backup sets
  586. :cleanup_archives_list
  587. echo.
  588. echo CURRENT BACKUP SETS:
  589. echo.
  590. echo IN STAGING          : ^(%STAGING%^)
  591. echo ---------------------
  592. dir /B /A:D "%STAGING%" 2>&1
  593. echo.
  594. echo.
  595. echo IN LONG-TERM STORAGE: ^(%DESTINATION%^)
  596. echo ---------------------
  597. dir /B /A:D "%DESTINATION%" 2>&1
  598. echo.
  599. :cleanup_archives_list2
  600. echo.
  601. set DAYS=180
  602. echo Delete backup sets older than how many days? ^(you will be prompted for confirmation^)
  603. set /p DAYS=[%DAYS%]?:
  604. if %DAYS%==exit goto end
  605. echo.
  606. :: Tell user what will happen
  607. echo THESE BACKUP SETS WILL BE DELETED:
  608. echo ----------------------------------
  609. :: List files that would match.
  610. :: We have to use PushD to get around forfiles.exe not using UNC paths. pushd automatically assigns the next free drive letter
  611. echo From staging:
  612. pushd "%STAGING%"
  613. FORFILES /D -%DAYS% /C "cmd /c IF @isdir == TRUE echo @path" 2>NUL
  614. popd
  615. echo.
  616. echo From long-term storage:
  617. pushd "%DESTINATION%"
  618. FORFILES /D -%DAYS% /C "cmd /c IF @isdir == TRUE echo @path" 2>NUL
  619. popd
  620. echo.
  621. set HMMM=n
  622. set /p HMMM=Is this okay [%HMMM%]?:
  623. if /i %HMMM%==n echo. && echo Canceled. Returning to menu. && goto cleanup_archives_list2
  624. if %DAYS%==exit goto end
  625. echo.
  626. set CHOICE=n
  627. set /p CHOICE=Are you absolutely sure [%CHOICE%]?:
  628. if not %CHOICE%==y echo. && echo Canceled. Returning to menu. && goto cleanup_archives_list2
  629. echo.
  630. echo  Okay, starting deletion.
  631.  
  632. :: Go ahead and do the cleanup.
  633. :cleanup_archives_go
  634. echo --------------------------------------------------------------------------------------------------->> %LOGPATH%\%LOGFILE%
  635. echo  Differential Backup Script v%VERSION% - initialized %CUR_DATE% at%TIME% by %USERDOMAIN%\%USERNAME%>> %LOGPATH%\%LOGFILE%
  636. echo.>> %LOGPATH%\%LOGFILE%
  637. echo  Script location:  %SCRIPT_NAME%>> %LOGPATH%\%LOGFILE%
  638. echo.>> %LOGPATH%\%LOGFILE%
  639. echo   Job type:        Delete archived backup sets older than %DAYS% days.>> %LOGPATH%\%LOGFILE%
  640. echo   Source:          %SOURCE%>> %LOGPATH%\%LOGFILE%
  641. echo   Destination:     %DESTINATION%>> %LOGPATH%\%LOGFILE%
  642. echo   Staging area:    %STAGING%>> %LOGPATH%\%LOGFILE%
  643. echo   Exclusions file: %EXCLUSIONS_FILE%>> %LOGPATH%\%LOGFILE%
  644. echo   Backup prefix:   %BACKUP_PREFIX%>> %LOGPATH%\%LOGFILE%
  645. echo   Log location:    %LOGPATH%\%LOGFILE%>> %LOGPATH%\%LOGFILE%
  646. echo   Log max size:    %LOG_MAX_SIZE% bytes>> %LOGPATH%\%LOGFILE%
  647. echo --------------------------------------------------------------------------------------------------->> %LOGPATH%\%LOGFILE%
  648. echo.>> %LOGPATH%\%LOGFILE%
  649. echo.
  650. echo %TIME%   Deleting backup sets that are older than %DAYS% days...>> %LOGPATH%\%LOGFILE%
  651. echo %TIME%   Deleting backup sets that are older than %DAYS% days...
  652.  
  653. :: This cleans out the staging area.
  654. :: First FORFILES command tells the logfile what will get deleted. Second command actually deletes.
  655. pushd "%STAGING%"
  656. FORFILES /D -%DAYS% /C "cmd /c IF @isdir == TRUE echo @path" >> %LOGPATH%\%LOGFILE%
  657. FORFILES /S /D -%DAYS% /C "cmd /c IF @isdir == TRUE rmdir /S /Q @path"
  658. popd
  659.  
  660. :: This cleans out the destination / long-term storage area.
  661. :: First FORFILES command tells the logfile what will get deleted. Second command actually deletes.
  662. pushd "%DESTINATION%"
  663. FORFILES /D -%DAYS% /C "cmd /c IF @isdir == TRUE echo @path" >> %LOGPATH%\%LOGFILE%
  664. FORFILES /S /D -%DAYS% /C "cmd /c IF @isdir == TRUE rmdir /S /Q @path"
  665. popd
  666.  
  667. echo.
  668. :: Report on the cleanup
  669. if %ERRORLEVEL%==0 (
  670.         echo %TIME%   Cleanup completed successfully.>> %LOGPATH%\%LOGFILE%
  671.         echo %TIME%   Cleanup completed successfully.
  672.         )
  673. if not %ERRORLEVEL%==0 (
  674.         set JOB_ERROR=1
  675.         echo %TIME% ! Cleanup completed with errors.>> %LOGPATH%\%LOGFILE%
  676.         echo %TIME% ! Cleanup completed with errors.
  677.         )
  678. goto done
  679.  
  680.  
  681. :::::::::::::::::::::::
  682. :: COMPLETION REPORT ::
  683. :::::::::::::::::::::::
  684. :done
  685. :: One of these displays if the operation was a restore operation
  686. if %RESTORE_TYPE%==full (
  687.         echo %TIME%   Restored full backup to %STAGING%\%BACKUP_PREFIX%>> %LOGPATH%\%LOGFILE%
  688.         echo %TIME%   Restored full backup to %STAGING%\%BACKUP_PREFIX%
  689.         )
  690.  
  691. if %RESTORE_TYPE%==differential (
  692.         echo.
  693.         echo %TIME%   Restored full and differential backup to %STAGING%\%BACKUP_PREFIX%>> %LOGPATH%\%LOGFILE%
  694.         echo %TIME%   Restored full and differential backup to %STAGING%\%BACKUP_PREFIX%
  695.         )
  696.  
  697. echo.
  698. echo %TIME%   %SCRIPT_NAME% complete.>> %LOGPATH%\%LOGFILE%
  699. echo %TIME%   %SCRIPT_NAME% complete.
  700. if '%JOB_ERROR%'=='1' echo. && echo %TIME% ! Note: Script exited with errors.>> %LOGPATH%\%LOGFILE%
  701. if '%JOB_ERROR%'=='1' echo. && echo %TIME% ! Note: Script exited with errors. Maybe check the log.
  702.  
  703. :end
  704. :: Clean up our temp exclude file
  705. if exist %TEMP%\DEATH_BY_HAMSTERS.txt del /F /Q %TEMP%\DEATH_BY_HAMSTERS.txt
  706. ENDLOCAL
Add Comment
Please, Sign In to add comment