Обновление службы в Windows на виртуалках-клонах

Опубликовано автор 0 comment

Windows Service или как я докатился до такой жизни?

Не хочется останавливаться на грустной истории, как я оказался перед архитектурой с несколькими Windows виртуалками , но мне досталось приложение которое имело следующую структуру:

Схема работы сервиса

Есть сайт которому для работы необходим сервис, написанный на C# и работающий под Windows. Этот сервис доступен на наружу по HTTP на реализует «типаREST» API. Сервис работает долго (в смысле время обработки одного запроса занимает значительное время), на одной машине может быть запущен в одном экземпляре, запросы обрабатывает последовательно. И из-за таких особенностей архитектура выросла в набор виртуалок-клонов, на которых работал сервис, а наружу они прикрывались linux узлом, на котором nginx выступал в качестве proxy балансировщика. А т.к. сервис (win-служба) — это «живое» приложение, в котором правятся баги, тюнится производительность и дорабатываются фичи, т.е. периодически появляются обновления. Руками разливать сервис по виртуалкам и перезапускать их — работа не благодарная, поэтому и родилась задача:
Необходима автоматическая система обновления сервиса. Для этого был написан загуглен batch скрипт.

Задача об обновление Windows Service, тезисно:

  • Есть бинарник, который лежит в системной папке винды, и который запущен как служба Windows. Есть линукс сервер со свежей версией сервиса. Win-машина по samba может стянуть свежую версию. Чтобы обновить сервис на винде нужно:
    • Оставить службу.
    • Перезаписать бинарник.
    • Запустить службу заново.
  • Помимо самой службы, есть файлы с контентом, которые иногда появляются и должны быть интегрированы в сервис, чтобы добавить их необходимо сделать следующие шаги:
    • Скопировать новые файлы на локальный диск сервиса.
    • Перезапустить сервис.

Решение первой задачи:

Все обновления будем складывать на linux сервак, который доступен виртуалкам по samba. Для решения задачи нам нужно знать две команды for и if

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
::Путь на удаленном сервере, где будет лежать новая версия сервиса
SET MAIN_SERVICE_FILES_PATH=...
::Локальное хранилище бинарника, за пределами системных папок
SET LOCAL_SERVICE_FILES_PATH=...
::Путь до бинарника в системной папке
SET WIN_SERVICE_FILES_PATH=C:\Windows\SysWOW64\...
::Файл с логами
SET UPDATER_LOG_FILE=c:\DO_NOT_DELETE\update.log

::Читаем дату модификации файла на сервере в переменную CUR_TS_DT
for %%i in (!MAIN_SERVICE_FILES_PATH!) do SET CUR_TS_DT=%%~ti
::Читаем дату модификации локального файла в переменную OLD_TS_DT
for %%i in (!WIN_SERVICE_FILES_PATH!) do SET OLD_TS_DT=%%~ti
::Преобразуем дату к строке, которую проще сравнивать
::Подпрограмма будет ниже, сделал такое тупое решение,
::изящное было делать лень :(
call :convert CUR_TS "!CUR_TS_DT!"
::Преобразуем вторую дату к строке
call :convert OLD_TS "!OLD_TS_DT!"

::Сравниваем даты
IF !CUR_TS! NEQ !OLD_TS! (
    ::Копируем бинарник на локальный диск
    COPY /Y !MAIN_SERVICE_FILES_PATH! !LOCAL_SERVICE_FILES_PATH!
    ::Останавливаем сервис ServiceName
    call sc stop ServiceName
    ::Копируем бинарник в системную директорию
    COPY /Y !LOCAL_SERVICE_FILES_PATH! !WIN_SERVICE_FILES_PATH!
    ::Запускаем сервис ServiceName
    call sc start ServiceName
    ::пишем в лог об обновлении
    echo %date% %time%: update >> !UPDATER_LOG_FILE!
) else (
    ::Если все хорошо, то радостно пишем это в лог
    echo %date% %time%: good >> !UPDATER_LOG_FILE!
)

 Решение второй задачи:

Задача примерно такая же, единственное нам нужно сравнивать две директории, и в случае нехватки файлов стягивать их. Ну и сервис перезапускать только в случае наличия обновлений.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
::Устанавливаем переменные с путями до файлов
SET MAIN_SERVICE_DATA_PATH=\\...
SET LOCAL_SERVICE_DATA_PATH=C:\...
SET HAS_NEW_FONTS=0

::Читаем удаленную директорию
for %%F in (!MAIN_SERVICE_DATA_PATH!*) do (
    ::Проверяем наличие локального файла с тем же именем
    if not exist "!LOCAL_SERVICE_DATA_PATH!%%~nxF" (
        ::Если файла нет то копируем его
        copy /Y "%%~fF" "!LOCAL_SERVICE_DATA_PATH!%%~nxF"
        ::Ставим флаг наличия обновлений
        SET HAS_NEW_FONTS=1
    )
)
::Если новые файлы появились
IF !HAS_NEW_FONTS!==1 (
    ::то перезапускаем сервис
    call sc stop ServiceName
    call sc start ServiceName
)

Подпрограмма преобразования даты:

В общем то комментировать нечего:

1
2
3
4
:convert
set t=%~2
set /a %1=%t:~8,2%%t:~3,2%%t:~0,2%%t:~11,2%%t:~14,2%
exit /b

P.S.

Первый блин, надеюсь не комом. К сожалению уже не восстановить источники информации откуда компоновался скрипт. Надеюсь кому-нибудь будет полезно. Жду комментариев.

VKLiveJournalПоделиться!
Разделы: Велосипеды | Tags: ,