WordPress バックアップ その2

 その1で設定ファイルやデータベースをバックアップすることにしたが、いつまでも増えていくのは気持ちが悪い。

 古い方から削除することにした。

Backup.bat

echo off
echo %DATE%-%TIME: =0% : Excecuting ... %0 %*
rem DATEの出力で、先頭に曜日が漢字一文字で表示されることがある。
rem その場合は設定-時計と言語-日付と時刻-日付と時刻の形式を変更するで、
rem 日付(短い形式)でyyyy/MM/ddを選ぶと曜日が出力されなくなるようだ。
rem OSのバージョンによっては、設定-時刻と言語-日付と時刻-日付、時刻、地域の書式設定-データ形式を変更する
if not "%1" == "" goto :BACKUP

setlocal

if not exist %~d0%~p0log mkdir %~d0%~p0log

set LOG_FILE=%~d0%~p0log\%COMPUTERNAME%_Backup_%date:~-10,4%-%date:~-5,2%-%date:~-2,2%.log

if "%WORDPRESS_BACKUP%" == "" (
    echo no backup placement >> %LOG_FILE% 2>&1
    echo set WORDPRESS_BACKUP=xxx >> %LOG_FILE% 2>&1
    endlocal

    EXIT /B
)

if not exist %LOG_FILE% (
    rem ログファイルへ出力するため、あえてファイルを通して呼び出す
    for %%f in (ProgramData Squid xampp) do call %0 %%f >> %LOG_FILE% 2>&1

    call BackupMySQL.bat 30 >> %LOG_FILE% 2>&1

    call DeleteOldFile.bat %~d0%~p0log %COMPUTERNAME%_backup_*.log 30 >> %LOG_FILE% 2>&1

    call DeleteOldFile.bat C:\ProgramData\win-acme\acme-staging-v02.api.letsencrypt.org\Log log-*.txt 90 >> %LOG_FILE% 2>&1
    call DeleteOldFile.bat C:\ProgramData\win-acme\acme-v02.api.letsencrypt.org\Log         log-*.txt 90 >> %LOG_FILE% 2>&1
)

endlocal

EXIT /B


:BACKUP

setlocal

if exist \%1 (
  if not "%WORDPRESS_BACKUP%" == "" (
      echo robocopy  \%1 %WORDPRESS_BACKUP%\%1 /S /XJ /XO /XX /XL /NP
      robocopy  \%1 %WORDPRESS_BACKUP%\%1 /S /XJ /XO /XX /XL /NP
  )
)

endlocal

EXIT /B

BackupMySQL.bat

@echo off
echo %DATE%-%TIME: =0% : Excecuting ... %0 %*
rem MAX_FILES 残す個数

setlocal

set /a MAX_FILES=0
if not "%1" == "" set /a MAX_FILES=%1

for %%i in (wp-01 wp-02) do call :MYSQLDUMP %%i %MAX_FILES%
endlocal

EXIT /B


:MYSQLDUMP

setlocal

if not exist %~d0%~p0MySQL mkdir %~d0%~p0MySQL
set SQL_FILE=%~d0%~p0MySQL\%COMPUTERNAME%_%1_%date:~-10,4%-%date:~-5,2%-%date:~-2,2%.sql

if not exist %SQL_FILE% (
    echo C:\xampp\mysql\bin\mysqldump -u -p %1
    C:\xampp\mysql\bin\mysqldump -u ユーザー名 -pパスワード %1 > %SQL_FILE%
    if errorlevel 1 goto :NO_FILE
    
    for %%f in (%SQL_FILE%) do (
        if %%~zf == 0 goto :NO_FILE
        if "%%~zf" == "" goto :NO_FILE
    )

    if not "%WORDPRESS_BACKUP%" == "" (
        if not exist %WORDPRESS_BACKUP%\xampp\Tools\MySQL mkdir %WORDPRESS_BACKUP%\xampp\Tools\MySQL
        echo copy /Y %SQL_FILE% %WORDPRESS_BACKUP%\xampp\Tools\MySQL\
        copy /Y %SQL_FILE% %WORDPRESS_BACKUP%\xampp\Tools\MySQL\
    )

    call DeleteOldFile.bat %~d0%~p0MySQL %COMPUTERNAME%_%1_*.sql %2
)

endlocal

EXIT /B

:NO_FILE

echo SQL output fail.

endlocal

EXIT /B 1

 DeleteOldFile.bat

@echo off
echo %DATE%-%TIME: =0% : Excecuting ... %0 %*
rem FOLDER フォルダー
rem PATERN ファイルパターン
rem MAX_FILES 残す個数

setlocal enabledelayedexpansion

set FOLDER=%1
set PATERN=%2
set /a MAX_FILES=0
if not "%3" == "" set /a MAX_FILES=%3

if %MAX_FILES% LEQ 0 (
    endlocal
    EXIT /B
)

rem "日時"+"ファイル名"の形式で一覧を作成する。本来はファイルへのマッチなので?*は使えない
set files=
for %%f in (%FOLDER%\%PATERN%) do (
  echo %%~nxf %%~tf
  for /F "usebackq delims=" %%a in (`forfiles /P %FOLDER% /M "%%~nxf" /C "cmd /c echo \"@fdate-@ftime\""+@file`) do (
      rem echo %%a
      set files=!files! %%a
  )
)

echo files=%files%
rem 逆順にソートする
for /F "usebackq delims=" %%a in (`qsort2.bat /r !files!`) do set filess=%%a
echo filess=%filess%

if "%filess%" == "" (
    echo stack overflow
    endlocal
    exit /b 1
)


set /a FILE_COUNT=0
for %%g in (%filess%) do (
  set /a FILE_COUNT=!FILE_COUNT! + 1
  if !FILE_COUNT! GTR %MAX_FILES% (
    for /F "tokens=2 delims=+" %%b in (%%g) do (
      set FILE=%%b
      del %FOLDER%\!FILE:~1!
    )
  )
)

endlocal

qsort.bat

@echo off
rem echo %DATE%-%TIME: =0% : Excecuting ... %0 %*
rem https://qa.codeflow.site/questions/133154/how-do-i-implement-quicksort-using-a-batch-file

setlocal enabledelayedexpansion

set REVERSE=

set sorted=
call :func_sort %*

echo %sorted%
endlocal

exit /b


:func_sort

rem shiftは%*を変更しないので、%*で呼ばれた後にshiftを使う
if /I "%1" == "/r" (
  set REVERSE=1
  shift /1
)

:sort_loop
  rem If we've only got one left, we're done.
  if /%2/ == // (
    set sorted=%sorted% %1
    rem You need to do this so that sorted is actually set before printing. 
    exit /b
  )

rem Check if it's in order.
if "%REVERSE%" == "" (
  if %1 LEQ %2 (
    rem add first value to sorted: 
    set sorted=%sorted% %1
    shift /1
    goto :sort_loop
  )
) else (
  if %1 GEQ %2 (
    rem add first value to sorted: 
    set sorted=%sorted% %1
    shift /1
    goto :sort_loop
  )
)

rem Out of order.
rem Reverse them and recursively resort.
set redo=%sorted% %2 %1
set sorted=
shift /1
shift /1

:redo_loop
  if not /%1/ == // (
    set redo=%redo% %1
    shift /1
    goto :redo_loop
  )


Call :sort_loop %redo%
rem When we get here, we'll have already echod our result.
exit /b

 batファイルで完結するソート方法であったが、ファイルが29個以上だとスタックの制限を超え、戻り値は””となった。

 仕方がないので、sort.exeを利用するバージョンを最終的に採用した。

qsort2.bat

@echo off
rem echo %DATE%-%TIME: =0% : Excecuting ... %0 %*

setlocal enabledelayedexpansion

set REVERSE=
if /I "%1" == "/r" (
  set REVERSE=/R
  shift /1
)

:TEMP_NAME
set TEMP_FILE=%TEMP%\sort_%RANDOM%.tmp
set TEMPO_FILE=%TEMP%\sorto_%RANDOM%.tmp
if exist %TEMP_FILE% goto :TEMP_NAME

rem ファイルに1行ずつ出力する
:LOOP

if "%1" == "" goto :LOOP_END

echo %1 >> %TEMP_FILE%
shift /1
goto :LOOP

:LOOP_END

sort.exe %REVERSE% %TEMP_FILE% /O %TEMPO_FILE%
if ERRORLEVEL 1 goto :ERR

set sorted=
for /F "delims=" %%a in (%TEMPO_FILE%) do set sorted=!sorted! %%a

del %TEMP_FILE%
del %TEMPO_FILE%

echo %sorted%
endlocal

exit /b

:ERR

endlocal

exit /b