Вопрос или проблема
У меня есть пакетный файл, который работал отлично на протяжении нескольких месяцев, но во время我的 отпуска он начал давать сбой — какой отличный момент! Временным решением является перезагрузка сервера 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.
указывает на то, что ваша команда не распознается как валидная из-за недостатка управления кавычками и пробелов в пути к файлу.
Исправление:
-
Проверка кавычек: Вам нужно убедиться, что вы правильно размещаете кавычки вокруг пути к
mariadb.exe
и других параметров. Путь к файлу с пробелами должен быть обернут в кавычки. - Корректный синтаксис: Обратите внимание на то, как вы формируете команду для
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
для корректного считывания имени файла, содержащего пробелы.
- Исполнение команды: После формирования команды, убедитесь, что вы ее правильно исполняете:
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, избегая ошибок, связанных с неправильным форматом команды. Если у вас возникнут другие проблемы, не стесняйтесь задавать дополнительные вопросы!