В моей предыдущей статье я описал пример скрипта, который может заархивировать и закинуть в облако определенный объем файлов пользователя без его участия, тем самым обеспечив простейшее резервное копирование файлов пользователя. Скрипт обеспечивает закрытие следующих вопросов:
Естественно, простота скрипта обернулась и его недостатками, а именно:
В связи с этим код скриптов полного и инкрементного архива был дополнен необходимым функционалом. Общее описание см. предыщущую статью, здесь я хочу остановиться лишь на изменениях.
call pass.bat xx x — вызов внешней программы, возвращающей обратно переменную xx со значением, указанным для идентификатора x.
Соответственно переменной user присваивается значение, привязанное к идентификатору 1 (имя пользователя учетной записи yandex), pass — 2 (пароль учетной записи yandex), pwd — 3 (пароль к архиву), recipient — 4 (почта, куда отправить лог операции).
Скрипт pass.bat приведен условно, метод защиты паролей может быть выбран другой, но для тех и этот вариант подходит, привожу самый простой код этого скрипта:
Данный код при его вызове находит рядом с собой файл pass.txt, и присваивает переменной, имя которой указано в первом аргументе вызова скрипта, значение той строки файла pass.txt, номер которой указан во втором аргументе вызова скрипта. Расположение файлов pass.bat и pass.txt не принципиально, лишь бы они лежали в одном каталоге, который указан в переменной path системы.
set mailsend=mailsend1.17b15.exe — указание программы для отправки отчета в почту пользователя. Отправка письма происходит с учетной записи yandex.ru, с которой происходит отправка файлов в облако.
set i=1 — установка счетчика попыток на 1
call :loging "-----------------------------------" — вызов процедуры логирования. Процедуре передается строка, которая далее записывается в 2 файла — файл лога %filebkp%-log.txt и отдельный файл текущих операций %filebkp%-log.tmp, который затем отправляется пользователю как отчет об результате архивирования.
Соответственно строки логирования в теле скриптов одновременно показывают пользователю совершаемые операции во время работы, записывают их в логи и для меня являются комментариями в теле скрипта, поясняющими что выполняется на последующих строках.
Соотвественно скрипт полного копирования и скрипт инкрементного копирования выполняют следующие операции:
Данные скрипты приведены лишь как примеры, переписывать под PowerShell пока нет желания, т.к. мне важно чтобы он работал на любой системе, включая Windows XP. Защиты от кражи паролей здесь нет, самому было бы интересно что предложили бы специалисты по безопасности, но разделение кода и паролей с возможностью размещения паролей в другом каталоге хотя бы снимает вероятность глупой ошибки, что при отправке скрипта другу ему же достанутся и пароли.
- быстрое (идеально в фоне);
- сохраняло бы как актуальную версию файлов, так и предыдущие;
- хранилище файлов было бы недоступно вирусам или стихийным бедствиям типа уничтожения носителя или его воровства;
- содержимое резевной копии было бы доступно только пользователю, т.е. паролировалось.
Естественно, простота скрипта обернулась и его недостатками, а именно:
- Хранение паролей в теле скрипта. Да, многие программы хранят пароли незашифрованными в текстовых файлах, и защита этих данных происходит через контроль доступа к файлам, но все таки вынести пароль из кода — это признак хорошего тона и минимальной защиты на случай, если каким то образом рабочий скрипт попадет в чужие руки.
- Отсутствие проверки успешного завершения операции, и откат к предыдущему состоянию в случае если операция не была успешно завершена.
- Отсутствие логирования и оповещения пользователя об успешности операции, если скрипт запускается через планировщик заданий.
В связи с этим код скриптов полного и инкрементного архива был дополнен необходимым функционалом. Общее описание см. предыщущую статью, здесь я хочу остановиться лишь на изменениях.
Скрипт создания полного архива
@echo off chcp 1251 >nul set filebkp=server call pass.bat user 1 call pass.bat pass 2 call pass.bat pwd 3 call pass.bat recipient 4 set mailsend=mailsend1.17b15.exe set i=1 set pathbkp=..\backup set pathtemp=..\temp set srvbkp=https://%user%:%pass%@webdav.yandex.ru/backup/%filebkp% set full=%filebkp%-full set inc=%filebkp%-inc set h=%TIME:~0,2% set m=%TIME:~3,2% set s=%TIME:~6,2% set ms=%TIME:~9,2% set curtime=%h%-%m%-%s% set dd=%DATE:~0,2% set mm=%DATE:~3,2% set yyyy=%DATE:~6,4% set curdate=%yyyy%-%mm%-%dd% set curdatetime=%curdate: =0%-%curtime: =0% call :loging "-----------------------------------" call :loging "Текущее время - %curdatetime%" call :loging "Создаем резервную копию текущих архивов" ren "%pathtemp%" temp-bkp md "%pathtemp%" call :loging "Создаем полный архив %full%.7z" 7z.exe a -xr0!*.log -xr0!*.bak -xr0!*.tmp "%pathtemp%\%full%".7z -r -mx1 "%pathbkp%\*" -%pwd% call :loging "Создаем резервную копию текущих архивов на сервере" curl.exe -k -X MOVE -H "Destination:/backup/%filebkp%"-bkp "%srvbkp%" -o .\stdout curl.exe -k -X MKCOL "%srvbkp%" -o .\stdout :upload call :loging "Попытка отправки номер %i%" call :loging "Отправляем на сервер файл %full%.7z" curl.exe -k -T "%pathtemp%\%full%".7z "%srvbkp%"/ --progress-bar -o .\stdout call :loging "Скачиваем файл %full%.7z с сервера для сравнения с исходным" curl.exe -k "%srvbkp%/%full%".7z -o "%pathtemp%"\test.7z --progress-bar -o .\stdout call :loging "Сравниваем скачанный файл с исходным" fc /LB1 /B "%pathtemp%\%full%".7z "%pathtemp%"\test.7z > nul if ERRORLEVEL 1 goto Different call :loging "Файлы одинаковы:" set tolog="%full%.7z успешно отправлен на сервер" call :loging %tolog% set mailsubject=%tolog:"=% call :loging "Удаляем устаревшие версии архива с компьютера и сервера" RD /s/q "%pathtemp%"-bkp curl.exe -k -X DELETE "%srvbkp%"-bkp -o .\stdout del /q "%pathtemp%"\test.7z goto exit :Different call :loging "Файлы различаются: %full%.7z на сервере НЕ совпадает с исходным" call :loging "Повторяем отправку" set /a i+=1 if %i% = 5 goto exit-f goto upload :exit-f set tolog="Отправка файла %full%.7z на сервер не удалась" call :loging %tolog% set mailsubject=%tolog:"=% call :loging "Восстанавливаем файлы предыдущего архива" RD /s/q "%pathtemp%" ren "%pathtemp%"-bkp temp curl.exe -k -X DELETE "%srvbkp%" -o .\stdout curl.exe -k -X MOVE -H "Destination:/backup/%filebkp%" "%srvbkp%"-bkp -o .\stdout :exit echo Отправляем лог %filebkp%-log.txt на сервер curl.exe -k -T %filebkp%-log.txt "%srvbkp%"/../ --progress-bar -o .\stdout echo Отправляем отчет в почту %mailsend% -to %recipient% -from %user%@yandex.ru -ssl -port 465 -auth -smtp smtp.yandex.ru -user %user% -pass %pass% -sub "%filebkp%: %curdatetime% - %mailsubject%" -cs "windows-1251" -mime-type "text/plain" -msg-body %filebkp%-log.tmp del /q %filebkp%-log.tmp exit :loging echo %~1 echo %~1 >> %filebkp%-log.txt echo %~1 >> %filebkp%-log.tmp exit /b
Скрипт создания инкрементного архива
@echo off chcp 1251 >nul set filebkp=server call pass.bat user 1 call pass.bat pass 2 call pass.bat pwd 3 call pass.bat recipient 4 set mailsend=mailsend1.17b15.exe set tolog=zero set mailsubject=zero set i=1 set pathbkp=..\backup set pathtemp=..\temp set srvbkp=https://%user%:%pass%@webdav.yandex.ru/backup/%filebkp% set full=%filebkp%-full set inc=%filebkp%-inc set h=%TIME:~0,2% set m=%TIME:~3,2% set s=%TIME:~6,2% set ms=%TIME:~9,2% set curtime=%h%-%m%-%s% set dd=%DATE:~0,2% set mm=%DATE:~3,2% set yyyy=%DATE:~6,4% set curdate=%yyyy%-%mm%-%dd% set curdatetime=%curdate: =0%-%curtime: =0% call :loging "-----------------------------------" call :loging "Текущее время - %curdatetime%" call :loging "Создаем инкрементный архив %inc%-%curdatetime%.7z" 7z.exe u -xr0!*.log -xr0!*.bak -xr0!*.tmp "%pathtemp%\%full%".7z -u- -up3q3r2x2y2z0w2!"%pathtemp%\%inc%-%curdatetime%".7z "%pathbkp%\*" -%pwd% :upload call :loging "Попытка отправки номер %i%" call :loging "Отправляем архив на сервер" curl.exe -k -T "%pathtemp%\%inc%-%curdatetime%".7z "%srvbkp%"/ --progress-bar -o .\stdout call :loging "Скачиваем архив с сервера для сравнения с исходным" curl.exe -k "%srvbkp%/%inc%-%curdatetime%".7z -o "%pathtemp%"\test.7z --progress-bar -o .\stdout call :loging "Сравниваем скачанный архив с исходным" fc /LB1 /B "%pathtemp%\%inc%-%curdatetime%".7z "%pathtemp%"\test.7z > nul if ERRORLEVEL 1 goto Different call :loging "Файлы одинаковы" set tolog="%inc%-%curdatetime%.7z успешно отправлен на сервер" call :loging %tolog% set mailsubject=%tolog:"=% goto exit :Different call :loging "Файлы различаются: %inc%-%curdatetime%.7z на сервере НЕ совпадает с исходным" call :loging "Повторяем отправку" set /a i+=1 if %i% = 5 goto exit-f goto upload :exit-f set tolog="Отправка файла %inc%-%curdatetime%.7z на сервер не удалась" call :loging %tolog% set mailsubject=%tolog:"=% :exit del /q "%pathtemp%"\test.7z echo Отправляем лог %filebkp%-log.txt на сервер curl.exe -k -T %filebkp%-log.txt "%srvbkp%"/../ --progress-bar -o .\stdout echo Отправляем отчет в почту %mailsend% -to %recipient% -from %user%@yandex.ru -ssl -port 465 -auth -smtp smtp.yandex.ru -user %user% -pass %pass% -sub "%filebkp%: %mailsubject%" -cs "windows-1251" -mime-type "text/plain" -msg-body %filebkp%-log.tmp del /q %filebkp%-log.tmp exit :loging echo %~1 echo %~1 >> %filebkp%-log.txt echo %~1 >> %filebkp%-log.tmp exit /b
Новые команды:
call pass.bat xx x — вызов внешней программы, возвращающей обратно переменную xx со значением, указанным для идентификатора x.
Соответственно переменной user присваивается значение, привязанное к идентификатору 1 (имя пользователя учетной записи yandex), pass — 2 (пароль учетной записи yandex), pwd — 3 (пароль к архиву), recipient — 4 (почта, куда отправить лог операции).
Скрипт pass.bat приведен условно, метод защиты паролей может быть выбран другой, но для тех и этот вариант подходит, привожу самый простой код этого скрипта:
for /f "usebackq delims=" %%i in (`find /n /v "" "%~dp0"pass.txt ^| find "[%2]"`) do ( set newvar=%%i ) set %1=%newvar:~3%
Данный код при его вызове находит рядом с собой файл pass.txt, и присваивает переменной, имя которой указано в первом аргументе вызова скрипта, значение той строки файла pass.txt, номер которой указан во втором аргументе вызова скрипта. Расположение файлов pass.bat и pass.txt не принципиально, лишь бы они лежали в одном каталоге, который указан в переменной path системы.
set mailsend=mailsend1.17b15.exe — указание программы для отправки отчета в почту пользователя. Отправка письма происходит с учетной записи yandex.ru, с которой происходит отправка файлов в облако.
set i=1 — установка счетчика попыток на 1
call :loging "-----------------------------------" — вызов процедуры логирования. Процедуре передается строка, которая далее записывается в 2 файла — файл лога %filebkp%-log.txt и отдельный файл текущих операций %filebkp%-log.tmp, который затем отправляется пользователю как отчет об результате архивирования.
Соответственно строки логирования в теле скриптов одновременно показывают пользователю совершаемые операции во время работы, записывают их в логи и для меня являются комментариями в теле скрипта, поясняющими что выполняется на последующих строках.
Соотвественно скрипт полного копирования и скрипт инкрементного копирования выполняют следующие операции:
- для полного архива — создает резервные копии текущих архивов на сервере и на локальном компьютере
- создает новую резервную копию
- пытается отправить её на сервер
- после отправки скачивает резервную копию и сравнивает с оригиналом
- в случае успеха сравнения — отправляет на сервер лог операций и пользователю в почту отчет об успешной операции через программу mailsend1.17b15.exe + для полного архива — удаляет устаревшие версии архива
- в случае обнаружения разницы между файлами — пытается выполнить повторную отправку файла на сервер, и если в течении 5 попыток отправка не удается — отправляет на сервер лог операций и пользователю в почту отчет об неудаче через программу mailsend1.17b15.exe:
- подчищает временный файл текущих операций.
P.S.
Данные скрипты приведены лишь как примеры, переписывать под PowerShell пока нет желания, т.к. мне важно чтобы он работал на любой системе, включая Windows XP. Защиты от кражи паролей здесь нет, самому было бы интересно что предложили бы специалисты по безопасности, но разделение кода и паролей с возможностью размещения паролей в другом каталоге хотя бы снимает вероятность глупой ошибки, что при отправке скрипта другу ему же достанутся и пароли.
