カテゴリー: サーバー管理

  • 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
  • WordPress シングルインスタンス―マルチデータベース

     一つの物理OS上で複数の仮想ホストを作成しそれぞれでwordpressのサイトを稼働させている。

     wordpressフォルダーを複数用意していたが、領域が二重に必要になったり、それぞれで更新するなど管理が面倒になってくる。

     データベースエンジンは1インスタンスだが、それぞれのサイトに専用のデータベースを利用している。

     そこで、複数サイトでそれぞれのデータベースを利用する設定ができないか試してみた。

    ここでは以下の3つの形態を説明している。

    1. WordPress マルチサイト機能 (単一のデータベースを持つ単一のWordPress インスタンス)
    2. 単一のデータベースを持つ複数の WordPress インスタンス
    3. 複数のデータベースを持つ複数の WordPress インスタンス

    しかし、以下のような形態には触れられていない。

    • 複数のデータベースを持つ単一のWordPressインスタンス

     ちなみに、ここでいうデータベースとは、データベースエンジン(xamppではMySQL)のことではなく、MySQLが管理している複数のデータベースのうちの一つのことらしい。ソフトウェア開発ではどちらも意味することがあるから前後の文脈から判断しないといけない。

     インスタンスは二つある気がするけど、複雑になるからこのままの表記で行おう。

     ここには、単一のデータベースを持つ単一のWordPressインスタンスで複数ドメインの運用例が載っている。

     ここを参考にして、修正を行った。

     /wordpress/wp-config.phpを以下のように書き変える。

    // homeとsiteurlの指定
    // homeで/wordpressが省略されているときは、siteurlに追加する
    $protocol = (!empty($_SERVER['HTTPS']) && $_SERVER['HTTPS'] !== 'off' || $_SERVER['SERVER_PORT'] == 443) ? "https://" : "http://";
    define( 'WP_HOME', $protocol . $_SERVER['HTTP_HOST']  );
    if (strpos(WP_HOME, '/wordpress') !== false) {
        define( 'WP_SITEURL', WP_HOME );
    } else {
        define( 'WP_SITEURL', WP_HOME . '/wordpress' );
    }
    
    // アップロードフォルダーの指定
    if ( strpos(WP_HOME, 'www2.') !== false ) {
    	define( "UPLOADS", "wp-content/uploads/www2" );
    }
    
    // ** MySQL 設定 - この情報はホスティング先から入手してください。 ** //
    /** WordPress のためのデータベース名 */
    // www2.domain.comのときはデータベースwp-02を指定する
    if (strpos(WP_HOME, 'www2.') !== false) {
    	define( 'DB_NAME', 'wp-02' );
    } else {
    	define( 'DB_NAME', 'wp-01' );
    }

     アップロードフォルダーも別にしたいので、指定を追加した。

     /wordpressを省略しているので、サイトトップのindex.phpも同じwordpressフォルダーを指すように変更しておく。

    require __DIR__ . '/../../wordpress/wp-blog-header.php';

     ダッシュボードの設定-一般を開くと、WordPress アドレス (URL)とサイトアドレス (URL)は入力できなくなっている。たぶん事前に定義されていたのは変更不可となるのだろう。なかなかかしこい。

     行儀の悪いプラグインとか動かない可能性もあるらしいが、様子見しよう。

  • WordPress バックアップ

     サーバー自体のバックアップとは別にWordPressの設定、データベースのバックアップを定期的に行う。

     設定ファイル等はrobocopyで存在するファイルのみ新しいものをコピーする。

     データベースは、SQLファイルとして毎日1回出力する。

     サーバー上に保存するとインスタンスを削除したときに消えてしまうのでローカルPCに保存する。そのため、リモート接続を行ったときにのみ行うこととした。

     あらかじめローカルPCにはバックアップしたい設定ファイル等のファイルを同じ階層構造でコピーしておく。

     システム環境変数にローカルPCのフォルダーパスを定義しておく。

    WORDPRESS_BACKUP=\\tsclient\C\Backup

     ローカルPCにファイルを保存するため、タスクスケジューラーでリモートデスクトップ接続したときに実行するように設定しておく。その際、ローカルリソースのCドライブを利用することを指定している。

    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 >> %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

     時刻が%TIME: =0%となっているのは、10:00より前は10時台が0サプレスされるのでスペースを0に置き換えている。

    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 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\
        )
    )
    
    endlocal
    
    EXIT /B

     mysqldumpのパスワード指定は、-pの後に空白を開けず続けて指定する。