17 мая 2010

Резервное копирование документов пользователей 7-zip

Как я писал ранее, мы начали изучать архиватор 7-zip более подробней.

7-zip
В нём нет возможности хранить версионность файлов в одном архиве. Однако, можно сделать несколько diff-архивов и тогда каждый из них будет хранить свою версию файлов. Другими словами, каждый Чаптер (chapter, терминология ARJ) располагается в отдельном файле. Точнее, будет один базовый архив и множество diff-архивов с изменениями относительно базового.

Анти-файл
Даже пригодился "анти-файл" (Анти-пункт, по терминологии 7-zip). Когда пользователь удалил файл, но в базовом архиве этот файл есть, то в diff-архиве создаётся "анти-файл". Грубо говоря, после распаковки базового архива файл создаётся на диске - ведщь в базовом архиве этот файл присутствует. А вот при распаковке diff-архива, анти-файл удаляет файл на диске.

Пишем батник
Батник решил написать мой коллега, nWhite.
Текст батника ниже. Краткий перечень интересных моментов:

  • "Самозапускаемый" батник для сворачивания в трей. Можно конечно написать еще один батник который будет запускай этот большой и обойтись без такого изврата, но это будет уже два батника:


REM При первом вызове батника он перезапускает себя,
REM чтобы запуститься свернутым и с низким приоритетом:
IF Not %1.==SecondStart. (
Start /Min /Low %~f0% SecondStart
Exit
)

  • Заголовок батника


ChCP 1251>Nul
Title "Архивация данных пользователя"
  • Создаём базовый архив
%ArchiverEXEPath% A %BaseArcPath% -ssw %ExcludeExt% %BackupFolder%\* -ms=off -mx=1 -mtc=on



  • Создаём diff-архив на основе базового архива

%ArchiverEXEPath% U %BaseArcPath% -ssw %ExcludeExt% -u- -up0q3r2x2z0!%DiffArcPath% %BackupFolder%\* -ms=off -mx=1 -mtc=on
Вот полный текст:
@Echo On

REM **********************************************************************
REM * Архивация данных пользователя (документы и рабочий стол) v1.0 beta *
REM *                почти копирайт Nikoluk/nWhite 2010                  *
REM *        Издание первое, не дополненное и не переработанное          *
REM **********************************************************************

REM При первом вызове батника он перезапускает себя,
REM чтобы запуститься свернутым и с низким приоритетом:
IF Not %1.==SecondStart. (
Start /Min /Low %~f0% SecondStart
Exit
)

ChCP 1251>Nul
Title "Архивация данных пользователя"

REM Парсим дату и время для использования их в переменных Year, Month и т.д.
Call :SetCurDateTime
REM Определяем расположения стандартных пользовательских папок
Call :SetUserEnvInfo

REM *** ОПРЕДЕЛЯЕМ ПЕРЕМЕННЫЕ *******************************
Set ArchiverEXEPath="\\Osprey\GPO\7-Zip\7z.exe"
Set ArcFolderPath="\\Osprey\Archives\%UserName%"
REM Путь к пользовательскому подробному логу:
Set LogPath="%ArcFolderPath%\log.txt"
REM Путь к общему краткому логу:
Set CommonLogPath="\\Osprey\Archives\CommonLog.txt"


Echo [%DATE% - %TIME%] Start User Backup [User: %UserName%; PC: %ComputerName%] >> %CommonLogPath%




REM Список исключений, всякую лабудень не архивим:
Set ExcludeExt=-XR!*.avi -XR!*.mkv -XR!*.mov -XR!*.vob -XR!*.flv -XR!*.3gp -XR!*.wmv -XR!*.asf -XR!*.mpg -XR!*.mp4 -XR!*.mp3 -XR!*.wav -XR!*.flac -XR!*.wv -XR!*.ape -XR!*.alac -XR!*.tmp

Set DeskBaseArcPath="%ArcFolderPath%\%Year%-%Month% [%UserName%] Desktop Base.7z"
Set DeskDiffArcPath="%ArcFolderPath%\%Year%-%Month%-%Day% [%UserName%] Desktop Diff.7z"
Set DocsBaseArcPath="%ArcFolderPath%\%Year%-%Month% [%UserName%] Documents Base.7z"
Set DocsDiffArcPath="%ArcFolderPath%\%Year%-%Month%-%Day% [%UserName%] Documents Diff.7z"
REM *********************************************************

IF Not Exist %ArcFolderPath% (
MkDir %ArcFolderPath%
IF Not %ErrorLevel%==0 (
Echo ERROR! Can't create archive folder! [%ArcFolderPath%] ErrorLevel=%ErrorLevel%
Pause
Exit
)
)

Echo ----------------------------------------------------------------------------- >> %LogPath%
Echo _ >> %LogPath%
Echo [%DATE% - %TIME%] ^> Start User Backup [User: %UserName%; PC: %ComputerName%] >> %LogPath%

REM Проверимс, есть ли архиватор по заданному пути:
IF Not Exist %ArchiverEXEPath% (
Echo Archiver EXE NOT FOUND! [%ArchiverEXEPath%] >> %LogPath%
GoTo TheEND
)


Set BackupName=DESKTOP
Set BackupFolder=%DesktopPath%
Set BaseArcPath=%DeskBaseArcPath%
Set DiffArcPath=%DeskDiffArcPath%
Call :Backup

Set BackupName=DOCUMENTS
Set BackupFolder=%MyDocsPath%
Set BaseArcPath=%DocsBaseArcPath%
Set DiffArcPath=%DocsDiffArcPath%
Call :Backup


:TheEND
Echo [%DATE% - %TIME%] ^< End User Backup >> %LogPath%

REM Вот и сказочке конец, а кто бекапит - маладэц! =)
Exit


REM ***********************************************************************
REM *************************** ПРОЦЕДУРЫ *********************************

:BackUp
REM *** Процедура архивации *********************************
REM *** Перед вызовом дополнительно нужно задать следующие переменные:
REM BackupName   - название бекапа, которое будет фигурировать в логе.
REM BackupFolder - путь к архивируемой папке.
REM BaseArcPath  - путь к базовому архиву.
REM DiffArcPath  - путь к дифференциальному архиву.
Echo [%DATE% - %TIME%]   Backuping user %BackupName%... [%BackupFolder%] >> %LogPath%

IF Not Exist %BackupFolder% (
Echo [%DATE% - %TIME%]   Folder %BackupFolder% NOT FOUND! >> %LogPath%
GoTo EndProc
)

REM Посмотрим, есть ли у нас базовый архив
IF Not Exist %BaseArcPath% (
Echo [%DATE% - %TIME%]   Search the BASE %BackupName% archive [%BaseArcPath%]... NOT FOUND. Creating BASE archive... >> %LogPath%
GoTo CreateBaseArc
) ELSE (
Echo [%DATE% - %TIME%]   Search the BASE %BackupName% archive [%BaseArcPath%]... FOUND. >> %LogPath%
IF Not Exist %DiffArcPath% (
Echo [%DATE% - %TIME%]   Search the DIFFERENTIAL %BackupName% archive [%DiffArcPath%]... NOT FOUND. Creating DIFFERENTIAL archive... >> %LogPath%
GoTo CreateDiffArc
) ELSE (
Echo [%DATE% - %TIME%]   Search the DIFFERENTIAL %BackupName% archive [%DiffArcPath%]... FOUND. No need %BackupName% backup. >> %LogPath%
)
)

REM Кажися, ниче архивить не надо (все украдено до нас). Валим отсюда...
GoTo EndProc

        
:CreateBaseArc
%ArchiverEXEPath% A %BaseArcPath% -ssw %ExcludeExt% %BackupFolder%\* -ms=off -mx=1 -mtc=on
Set ErrLevel=%ErrorLevel%
Call :SetErrorDescription
Echo [%DATE% - %TIME%]   Done. ErrorLevel = %ErrLevel%, %ErrorDescription% >> %LogPath%
IF Not Exist %BaseArcPath% (
REM Вот ужасть-то какая, а архива-то нету...
[%DATE% - %TIME%]   Echo ERROR! Archive %BaseArcPath% NOT FOUND! >> %LogPath%
)
GoTo EndProc

:CreateDiffArc
%ArchiverEXEPath% U %BaseArcPath% -ssw %ExcludeExt% -u- -up0q3r2x2z0!%DiffArcPath% %BackupFolder%\* -ms=off -mx=1 -mtc=on
Set ErrLevel=%ErrorLevel%
Call :SetErrorDescription
Echo [%DATE% - %TIME%]   Done. ErrorLevel = %ErrLevel%, %ErrorDescription% >> %LogPath%
IF Not Exist %DiffArcPath% (
REM Вот ужасть-то какая, а архива-то нету...
Echo [%DATE% - %TIME%]   ERROR! Archive %DiffArcPath% NOT FOUND! >> %LogPath%
)
GoTo EndProc

:EndProc
Exit /b

:SetCurDateTime
REM Парсинг даты и времени
For /f "Tokens=1-3 Delims=./-" %%A In ("%Date%") Do (
   Set Day=%%A
   Set Month=%%B
   Set Year=%%C
)
For /f "Tokens=1-3 Delims=:," %%A In ("%Time%") Do (
   Set Hours=%%A
   Set Minutes=%%B
Set Seconds=%%C
)
Exit /b

:SetUserEnvInfo
REM *** Определение расположения стандартных пользовательских папок ***
For /f "Tokens=2*" %%i In ('Reg Query "HKCU\Software\Microsoft\Windows\CurrentVersion\Explorer\Shell Folders" /v Desktop ^| FindStr /s /i Reg_sz') Do (
Set DesktopPath="%%j"
)
REM Если путь к десктопу начинается с %UserProfile%, 
REM сделаем обходной маневр, чтобы путь расшифровался.
REM (если в пути используется какая-либо другая 
REM переменная среды - сори, не повезло, "кина не будет")
IF Not %DesktopPath%.==. (
IF /i %DesktopPath:~2,11%==UserProfile (
Set DesktopPath="%UserProfile%%DesktopPath:~14,300%
)
)
For /f "Tokens=2*" %%i In ('Reg Query "HKCU\Software\Microsoft\Windows\CurrentVersion\Explorer\Shell Folders" /v Personal ^| FindStr /s /i Reg_sz') Do (
Set MyDocsPath="%%j"
)
IF Not %MyDocsPath%.==. (
IF /i %MyDocsPath:~2,11%==UserProfile (
Set MyDocsPath="%UserProfile%%MyDocsPath:~14,300%
)
)
Exit /b

:SetErrorDescription
REM Расшифровка ErrorLevel'а 7-Zip'а:
IF %ErrLevel%==0   Set ErrorDescription=No Errors
IF %ErrLevel%==1   Set ErrorDescription=Warning (Non fatal error(s)). For example, one or more files were locked by some other application, so they were not compressed.
IF %ErrLevel%==2   Set ErrorDescription=Fatal error
IF %ErrLevel%==7   Set ErrorDescription=Command line error 
IF %ErrLevel%==8   Set ErrorDescription=Not enough memory for operation
IF %ErrLevel%==255 Set ErrorDescription=User stopped the process
Exit /b

1 комментарий:

Valery Moskalenko комментирует...

Странно. Я через 10 лет использую этот скрипт для бекапа кода. У клиента сдох Azure DevOps - а код лучше хоть как-то бекапить.