Проблема пакетного файла с динамическим вызовом импорта MariaDB

Вопрос или проблема

У меня есть пакетный файл, который работал отлично на протяжении нескольких месяцев, но во время我的 отпуска он начал давать сбой — какой отличный момент! Временным решением является перезагрузка сервера mariadb каждый день… это не идеал.

Я затем попытался добавить несколько параметров в mysqldump, и это, похоже, сработало. Когда я начал изменять вызов для импорта данных, я получил несколько различных ошибок в зависимости от того, что я пробовал. Это текущий пакетный файл, позже я поделюсь оригинальными двумя строками кода, которые работали, но в них также нужно добавить foreign_key_checks.

Пакетный файл

@echo off
setlocal enableDelayedExpansion

REM Получаем текущую дату в формате YYYYMMDD
set "dt=%date:~0,4%%date:~5,2%%date:~8,2%"

REM Определяем путь к резервным копиям
set "backups_path=%~dp0backups\"

REM Создаем папку для резервных копий, если она не существует
if not exist "%backups_path%" mkdir "%backups_path%"

REM Загружаем массив местоположений и длину местоположений
call load_locations.bat

REM Цикл по каждому местоположению
for /l %%x in (0, 1, %locations_len%) do (
    REM Формируем динамический полный путь для каждого местоположения
    set "dump_file=%backups_path%!locations[%%x].brand!_!locations[%%x].name!_!locations[%%x].db!_%dt%.sql"
    set "file_name=!locations[%%x].brand!_!locations[%%x].name!_!locations[%%x].db!_%dt%.sql"

    IF NOT "%~1"=="--no-dump" (
        REM Удаляем старые резервные копии для этого местоположения, оставляя только последние две
        call :printMessage "Очистка старых резервных копий для местоположения !locations[%%x].db!"
        for /f "skip=2 delims=" %%f in ('dir /b /o-d "%backups_path%!locations[%%x].brand!_!locations[%%x].name!_!locations[%%x].db!_*.sql"') do (
            del "%backups_path%%%f"
            call :printMessage "Удален старый файл резервной копии: %%f"
        )

        REM Выполняем mysqldump
        call :printMessage "Экспорт базы данных !locations[%%x].db! в !file_name!"
        mysqldump --login-path=!locations[%%x].name! --single-transaction --quick --opt --extended-insert --disable-keys --add-drop-table --set-gtid-purged=OFF !locations[%%x].db! > !dump_file!

        IF ERRORLEVEL 1 (
            call :printMessage "mysqldump завершился с ошибкой для базы данных !locations[%%x].db!"
            goto:eof
        ) ELSE (
            call :printMessage "Экспорт базы данных !locations[%%x].db! успешно завершен."
        )
    )

    IF EXIST !dump_file! (
        call :printMessage "Импортируем файл дампа !file_name! в базу данных !locations[%%x].db!"

    REM Формируем команду импорта MariaDB
    set "cmd_mariadb="C:\Program Files\MariaDB 11.2\bin\mariadb.exe" --defaults-extra-file="C:\Matt\dev\kpis\mariadb_login.ini" !locations[%%x].db! -e \"SET foreign_key_checks=0; source !dump_file!; SET foreign_key_checks=1;\""

    REM Выполняем команду импорта MariaDB
    REM call !cmd_mariadb!
    cmd /c %cmd_mariadb%

        IF ERRORLEVEL 1 (
            call :printMessage "Импорт MariaDB завершился с ошибкой для !locations[%%x].db!"
            goto:eof
        ) ELSE (
            call :printMessage "Импорт базы данных !locations[%%x].db! успешно завершен."
        )
    ) ELSE (
        call :printMessage "Файл дампа !dump_file! не найден, пропускаем импорт."
    )
)

endlocal
goto:eof

REM Функция для вывода сообщений как в консоль, так и в файл лога
:printMessage
echo %dt% - %time:~0,8% - %~1 >> "%~dp0logs.txt"
echo %dt% - %time:~0,8% - %~1
goto:eof

load_location.bat

@echo off

:: Устанавливает настройки местоположения 1
set locations[0].brand=aaa
set locations[0].name=a
set locations[0].db=a

:: Устанавливает настройки местоположения 2
set locations[1].brand=bbb
set locations[1].name=b
set locations[1].db=b

:: Находим количество мест, по которым нужно пройти
set locations_len=0 

:Loop 
if defined locations[%locations_len%].name ( 
set /a locations_len+=1
GOTO :Loop 
)

:: Корректируем длину для цикла for
set  /a locations_len-=1

mariadb_login.ini

[client]
user=batch_user
password=password
host=127.0.0.1
port=3306

Сообщение об ошибке

C:\Matt\dev\kpis>dump_load_allezup_rgp3.bat 
20240917 - 13:40:47 - Очистка старых резервных копий для местоположения a 
20240917 - 13:40:47 - Экспорт базы данных a в file_20240917.sql 
20240917 - 13:43:03 - Экспорт a успешно завершен. 
20240917 - 13:43:03 - Импортируем файл дампа file_20240917.sql в базу данных allezup '""C:\Program' не распознается как внутренняя или внешняя команда, исполняемая программа или пакетный файл. 
20240917 - 13:43:03 - Импорт MariaDB завершился с ошибкой для a

Я пробовал использовать ” и “”

Также пробовал

    set cmd_mariadb="\"C:\Program Files\MariaDB 11.2\bin\mariadb.exe\" --defaults-extra-file=\"C:\Matt\dev\kpis\mariadb_login.ini\" !locations[%%x].db! -e \"SET foreign_key_checks=0; source '\"!dump_file!\"'; SET foreign_key_checks=1;\""

Я использовал GPT, да, я знаю, и не смог добиться большого прогресса:

Предыдущая версия этого файла была слишком медленной, поэтому я попытался добавить параметры, чтобы ускорить процесс и избежать тайм-аута сервера mariadb.

    set cmd_mariadb="C:\Program Files\MariaDB 11.2\bin\mariadb.exe" --defaults-extra-file=C:\Matt\dev\kpis\mariadb_login.ini !locations[%%x].db! -e "source !dump_file!"
    call !cmd_mariadb!

Ответ или решение

Чтобы решить проблему с динамическим вызовом импорта MariaDB в вашем пакетном файле, вам необходимо проверить несколько моментов в вашем коде и убедиться, что команды формируются и исполняются корректно.

Проблема:

Ошибка, которую вы видите:

'""C:\Program' is not recognized as an internal or external command, operable program or batch file.

указывает на то, что ваша команда не распознается как валидная из-за недостатка управления кавычками и пробелов в пути к файлу.

Исправление:

  1. Проверка кавычек: Вам нужно убедиться, что вы правильно размещаете кавычки вокруг пути к mariadb.exe и других параметров. Путь к файлу с пробелами должен быть обернут в кавычки.

  2. Корректный синтаксис: Обратите внимание на то, как вы формируете команду для cmd. Приведите команду к следующему виду:
set "cmd_mariadb=C:\Program Files\MariaDB 11.2\bin\mariadb.exe --defaults-extra-file=C:\Matt\dev\kpis\mariadb_login.ini !locations[%%x].db! -e \"SET foreign_key_checks=0; source '!dump_file!'; SET foreign_key_checks=1;\""

Здесь вы просто убрали лишние кавычки отсутствующие ранее, а также использовали одинарные кавычки вокруг !dump_file! в строке source для корректного считывания имени файла, содержащего пробелы.

  1. Исполнение команды: После формирования команды, убедитесь, что вы ее правильно исполняете:
cmd /c !cmd_mariadb!

Полный код вашего пакетного файла с исправлениями:

@echo off
setlocal enableDelayedExpansion

REM Получаем текущую дату в формате YYYYMMDD
set "dt=%date:~0,4%%date:~5,2%%date:~8,2%"

REM Определяем путь к бэкапам
set "backups_path=%~dp0backups\"

REM Создаем папку backups, если ее не существует
if not exist "%backups_path%" mkdir "%backups_path%"

REM Загружаем массив местоположений и длину массива
call load_locations.bat

REM Цикл по каждому местоположению
for /l %%x in (0, 1, %locations_len%) do (
    set "dump_file=%backups_path%!locations[%%x].brand!_!locations[%%x].name!_!locations[%%x].db!_%dt%.sql"
    set "file_name=!locations[%%x].brand!_!locations[%%x].name!_!locations[%%x].db!_%dt%.sql"

    IF NOT "%~1"=="--no-dump" (
        call :printMessage "Очистка старых резервных копий для местоположения !locations[%%x].db!"
        for /f "skip=2 delims=" %%f in ('dir /b /o-d "%backups_path%!locations[%%x].brand!_!locations[%%x].name!_!locations[%%x].db!_*.sql"') do (
            del "%backups_path%%%f"
            call :printMessage "Удален старый файл резервной копии: %%f"
        )

        call :printMessage "Экспорт базы данных !locations[%%x].db! в !file_name!"
        mysqldump --login-path=!locations[%%x].name! --single-transaction --quick --opt --extended-insert --disable-keys --add-drop-table --set-gtid-purged=OFF !locations[%%x].db! > !dump_file!

        IF ERRORLEVEL 1 (
            call :printMessage "mysqldump завершился неудачно для базы данных !locations[%%x].db!"
            goto:eof
        ) ELSE (
            call :printMessage "Экспорт !locations[%%x].db! завершен успешно."
        )
    )

    IF EXIST !dump_file! (
        call :printMessage "Импортирую дамп файл !file_name! в базу данных !locations[%%x].db!"

        REM Формируем команду для импорта
        set "cmd_mariadb=C:\Program Files\MariaDB 11.2\bin\mariadb.exe --defaults-extra-file=C:\Matt\dev\kpis\mariadb_login.ini !locations[%%x].db! -e \"SET foreign_key_checks=0; source '!dump_file!'; SET foreign_key_checks=1;\""

        REM Выполняем команду импорта
        cmd /c !cmd_mariadb!

        IF ERRORLEVEL 1 (
            call :printMessage "Импорт MariaDB завершился неудачно для !locations[%%x].db!"
            goto:eof
        ) ELSE (
            call :printMessage "Импорт !locations[%%x].db! завершен успешно."
        )
    ) ELSE (
        call :printMessage "Дамп файл !dump_file! не найден, пропуск импорта."
    )
)

endlocal
goto:eof

REM Функция для вывода сообщений в консоль и в лог файл
:printMessage
echo %dt% - %time:~0,8% - %~1 >> "%~dp0logs.txt"
echo %dt% - %time:~0,8% - %~1
goto:eof

Заключение

Применив указанные исправления, ваш пакетный файл должен корректно выполнять импорт дампов в MariaDB, избегая ошибок, связанных с неправильным форматом команды. Если у вас возникнут другие проблемы, не стесняйтесь задавать дополнительные вопросы!

Оцените материал
Добавить комментарий

Капча загружается...