バックアップ・リストアの記事は、以前こちらでも紹介しました

- 新しいBASH
- デバッグ
- スクリプト構成
- WordPress_Config_Data.sh : 変数設定
- Wp-Backup.sh : データベース&WordPressコンテンツのバックアップ
- MariaDB_Backup.sh : データベースバックアップ(Wp-Backup.shから呼ばれる)
- Wp-Content_Backup.sh : WordPressコンテンツバックアップ(Wp-Backup.shから呼ばれる)
- Wp-Restore.sh : データベース&WordPressコンテンツの復元
- MariaDB_Restore.sh データベース復元(Wp-Restore.shから呼ばれる)
- Wp-Content_Restore.sh: WordPressコンテンツ復元(Wp-Restore.shから呼ばれる)
- Header.sh : デバッグモード仕様(変数 DEBUG=1 で有効)
- Tidyup_backfile.sh : バックアップファイルの整理(引数:対象ディレクトリ・保存日数)
- 自動バックアップ
新しいBASH
前回のスクリプトは、2020年に紹介したコマンド操作をネット情報を参考にスクリプト化しましたが、今回はこのスクリプトをAIに投げて、最新のBASH構文への変換を教えてもらいながら作成しました。
投稿のスクリプト類はちょっと長くなりましたが、全てコピペできるようにしました。
また、開発途中ではBASHで一行づつのデバッグもやってみました。
デバッグ
編集はVSCodeを利用したので、デバッグプラグインもインストールしてみましたが、あまり思ったように動いてくれませんでした。
AIに聞いてみると、BASH自体にも、構文チェックやステップデバッグができる機能があるようです
shellcheck
のようにコマンド実行するだけで、スクリプトのバグや構文エラーを簡単にチェックできます。
パッケージ名は、キャメルケース的書き方「ShellCheck」になるので注意が必要です
sudo dnf install ShellCheck
もしパッケージが見つからない場合には、EPELリポジトリが有効になっていない可能性があるのでEPELを有効化した上で再度インストール
sudo dnf install epel-release
sudo dnf install ShellCheck
shellcheck は、スクリプトのバグや構文エラーを検出してエラーコードと共に表示してくれます。
標準では致命的でない場合でも警告を出してくるのでちょっとうるさく感じる事もありますが、
エラーコードをAIに聞くことでより安全なコードの書き方の学習にもなります
set コマンド
Bashの set コマンドは、シェルの動作やオプションを設定・変更するためのコマンドです。
主にスクリプトの安全運転モードやデバッグのために、シェルの冒頭でオプションと組み合わせて使用されます
・set -euo pipefail
実務でよく使われる定番のオプション
これにより、スクリプト実行時のバグや予期せぬトラブルを大幅に減らせます
・set -x: デバッグ開始
実行されるコマンドや変数の展開結果をすべて画面(標準エラー出力)に表示
・set +x: デバッグ開始
実行トレース出力を停止
・trap ‘read -p “STEP> ” < /dev/tty’ DEBUG
実行中、すべてのコマンドを実行する直前で指定文字(STEP>)プロンプトで一時停止
・export PS4=’+ ${LINENO}: ‘
デバッグモード(set -x)で実行されるコマンドを表示する際、そのコマンドのスクリプトでの行番号を出力に含める設定
これらコードをスクリプト上部で実行しておくことで、シェルスクリプトのバグの原因特定が早くなります。
サンプルコードを書いてみました。
#!/bin/bash
set -euo pipefail
# --- debug mode: DEBUGGING=1 で有効 ---
DEBUGGING=1
if [[ $DEBUGGING == "1" ]]; then
echo "Debug mode is 'true' !! "
export PS4='+ ${LINENO}: '
set -x
trap 'read -p "STEP> " < /dev/tty' DEBUG
else
echo "Debug mode is 'false' !! "
fi
# テスト用コード
echo "最初の処理"
x=10
y=20
result=$((x + y))
echo "結果は $result"
このコードを実行すると、デバッグの状況が体験できます
次に今回作成したWordPressのバックアップ&リストアのスクリプトを紹介します
デバッグコードは、Header.sh に別スクリプトにして、呼び出す形式にしました。
スクリプト構成
WordPressのバックアップは、大きく分けて「ファイル(サーバー内のデータ)」と「データベース(MySQL/MariaDB)」の2つが必要になります。
前回スクリプトは、昔の経験とネット検索を参考に、自分で作成しましたが
今回は、BASHもかなり進化しているみたいなので、AIのサポートで最新の構文で書き直しました。
バックアップファイルやスクリプトの構成は
・「ユーザーホーム」内に、「Backup」ディレクトリを作成
・「Backup」内に、「WordPress」と「bin」ディレクトリを作成
・「WordPress」内にWordPress パッケージをインストールしたディレクトリ名(筆者環境では「blog」)を作成します
・「blog」内に、データベースとサーバー内データのバックアップを保存します
・「bin」内に実行スクリプトを保存します
.[ユーザーホームディレクトリ]
├── Backup #「バックアップデータを保存する」
│ ├── WordPress #「WordPerss関連データ」
│ │ └── blog #「blog内のバックアップデータ」
│ │ ├── 20260530-MariaDB.bak # データベースバックアップ
│ │ ├── 20260530-Wp-content.tar.gz # WordPressコンテンツ
│ │ ├── mariadb_backup.log
│ │ └── wp_backup.log
│ ├── bin #「スクリプト」
│ │ ├── Header.sh #「デバッグ用のスクリプト」
│ │ ├── MariaDB_Backup.sh #「データベースのバックアップ」
│ │ ├── MariaDB_Restore.sh #「データベースのリストア」
│ │ ├── Tidyup_backfile.sh #「バックアップデータの整理」
│ │ ├── WordPress_Config_Data.sh #「バックアップ環境の設定」
│ │ ├── Wp-Backup.sh #「バックアップ用メインスクリプト」
│ │ ├── Wp-Content_Backup.sh #「WordPressデータのバックアップ」
│ │ ├── Wp-Content_Restore.sh #「WordPressデータのリストア」
│ │ └── Wp-Restore.sh #「リストア用メインスクリプト」
WordPress_Config_Data.sh : 変数設定
#!/bin/bash
# WoredPressバックアップ設定ファイル
# WordPress_Config_Data.sh 2026/05 by Kazuban
#------------------------------------
export USER="kazuban"
export USER_DIR="/home/${USER}"
export SUB_DIR="blog"
export DOCUMEN_ROOT="/home/www/html"
#----- MariaDB ----------------------
export MYSQL_ROOT_PASSWD="hogehoge_passwd"
export DATABASE="WpDb"
export MYSQL_USER="WpAdmin"
export MYSQL_USER_PASSWD="WpPasswd"
#----- WordPress --------------------
export WP_CONTENT_DIR="wp-content"
export WP_CONTENT_FILENAME="Wp-content"
export WP_CONTENT_PATH="/home/www/html/${SUB_DIR}/${WP_CONTENT_DIR}"
export WP_CONTENT_OWNER="apache:apache"
Wp-Backup.sh : データベース&WordPressコンテンツのバックアップ
#!/bin/bash
# WoredPress のバックアップ
# データベース(Mysql)とサーバーデータ(wp-content)
# Wp-Backup.sh 2026/05 by Kazuban
#------------------------------------
#--- debug mode, set "DEBUG=1". -----
export DEBUG=
#------------------------------------
export CALLER_SCRIPT="$0"
#export SCRIPT_DIR=$(dirname "$(realpath "$0")")
#shellscriptで警告でたので、AIに聞くとこの書き方が安全らしい
SCRIPT_DIR=$(dirname "$(readlink -f "${BASH_SOURCE[0]}")")
export SCRIPT_DIR
#------------------------------------
source "${SCRIPT_DIR}/Header.sh"
source "${SCRIPT_DIR}/WordPress_Config_Data.sh"
export BACKUP_DIR="${USER_DIR}/Backup/WordPress/${SUB_DIR}"
#---- MariaDB -----------------------
export MYSQL_BACKUP_SCRIPT="${SCRIPT_DIR}/MariaDB_Backup.sh"
export MYSQL_LOG="${BACKUP_DIR}/mariadb_backup.log"
#---- WordPress ---------------------
#export BACKUP_SOURCE_DIR="${DOCUMEN_ROOT}/${SUB_DIR}/wp-content"
export WP_BACKUP_SCRIPT="${SCRIPT_DIR}/Wp-Content_Backup.sh"
export BACKUP_SOURCE_DIR="${DOCUMEN_ROOT}/${SUB_DIR}/${WP_CONTENT_DIR}"
export WP_LOG="${BACKUP_DIR}/wp_backup.log"
#------------------------------------
export TIDY_UP_SCRIPT="${SCRIPT_DIR}/Tidyup_backfile.sh"
export DAYS_AGO="5"
#----- 関数定義 -----------------------
user_dir=$(pwd)
echo $user_dir
# スクリプト終了時に実行させたい場合はここで再定義
cleanup() {
# echo "Wp-Backup 終了処理"
:
}
check_backup_dir(){
#$BACKUP_DIRが存在しない場合には作成
mkdir -p $BACKUP_DIR
}
cmd_mariadb() { check_backup_dir; $MYSQL_BACKUP_SCRIPT; }
cmd_wordpress() { check_backup_dir; $WP_BACKUP_SCRIPT; }
cmd_all() { cmd_mariadb; cmd_wordpress; }
cmd_help() {
echo "--- WordPress Backup Script ---"
echo "Directory: ${SCRIPT_DIR}"
echo "Usage: $0 {db|wp|all|help}"
echo " db = データベース(MariaDB)"
echo " wp = Word Press (Wp-Content)"
echo " all = db + wp"
echo " help = オプション"
}
#----- メインプログラム -------------
#------------------------------------
case "${1:-}" in
db) cmd_mariadb ;;
wp) cmd_wordpress ;;
all) cmd_all ;;
help|"") cmd_help ;;
*)
echo "Unknown command: $1"
cmd_help
exit 1
;;
esac
MariaDB_Backup.sh : データベースバックアップ(Wp-Backup.shから呼ばれる)
#!/bin/bash
# WoredPress のデータベースバックアップ
# MariaDB_Backup.sh 2026/05 by Kazuban
#------------------------------------
# 直接実行ガード(呼び出し元スクリプトからのみ実行可)
if [[ -z "${CALLER_SCRIPT:-}" ]]; then
echo "直接実行はできません。"
echo "[WP-Backup.sh db] から呼び出してください。"
exit 1
fi
#------------------------------------
source "${SCRIPT_DIR}/Header.sh"
#------------------------------------
# --- 関数定義 ---
usage() {
echo "使用方法: ${SCRIPT_NAME:-$(basename "$0")}"
echo " データベース(MariaDB)をバックアップし、古いファイルを整理します。"
exit 0
}
log() {
local message="$1"
echo "$(date '+%Y-%m-%d %H:%M:%S') ${message}" | tee -a "${MYSQL_LOG}"
}
failed() {
echo "エラー: $1" >&2
log "ERROR: $1"
exit 1
}
# バックアップファイル名を生成する(同名ファイルがあれば連番を付加)
make_filename() {
local date_str
date_str=$(date '+%Y%m%d')
local basename="-MariaDB.bak"
local filename="${date_str}${basename}"
local i=1
while [[ -e "${BACKUP_DIR}/${filename}" ]]; do
filename="${date_str}-${i}${basename}"
(( i++ )) || true
done
echo "${filename}"
}
# --- ヘルプ ---
if [[ "${1:-}" == "-?" || "${1:-}" == "-h" || "${1:-}" == "--help" ]]; then
usage
fi
# --- 事前チェック ---
[[ -d "${BACKUP_DIR}" ]] || failed "バックアップ先が見つかりません: ${BACKUP_DIR}"
[[ -x "${TIDY_UP_SCRIPT}" ]] || failed "整理スクリプトが見つかりません: ${TIDY_UP_SCRIPT}"
# --- ファイル名決定 ---
FILENAME=$(make_filename)
BACKUP_PATH="${BACKUP_DIR}/${FILENAME}"
# --- バックアップ実行 ---
log "MariaDB バックアップ開始: ${FILENAME}"
echo "MariaDB を ${FILENAME} にバックアップします。"
if mariadb-dump \
--user="${MYSQL_USER}" \
--password="${MYSQL_USER_PASSWD}" \
--host=localhost \
--all-databases \
--single-transaction \
--quick \
> "${BACKUP_PATH}" \
2>> "${MYSQL_LOG}"; then
log "バックアップ成功: ${FILENAME} ($(du -sh "${BACKUP_PATH}" | cut -f1))"
else
failed "mariadb-dump コマンドが失敗しました"
fi
# --- 古いファイルの整理 ---
log "古いバックアップを整理します(${DAYS_AGO} 日以前)"
"${TIDY_UP_SCRIPT}" "${BACKUP_DIR}" "${DAYS_AGO}"
log "MariaDB バックアップ完了"
echo "MariaDB Backup Complete."
Wp-Content_Backup.sh : WordPressコンテンツバックアップ(Wp-Backup.shから呼ばれる)
#!/bin/bash
# wp-content ディレクトリのバックアップスクリプト
# WP-content_Backup.sh 2026/05 by Kazuban
#------------------------------------
# 直接実行ガード(呼び出し元スクリプトからのみ実行可)
if [[ -z "${CALLER_SCRIPT:-}" ]]; then
echo "直接実行はできません。"
echo "[WP-Backup.sh wp] から呼び出してください。"
exit 1
fi
#------------------------------------
readonly SCRIPT_NAME="$(basename "$0")"
#------------------------------------
source "${SCRIPT_DIR}/Header.sh"
#------------------------------------
# スクリプト終了時に実行させたい場合はここで再定義
cleanup() {
# echo "Wp-Backup 終了処理"
:
}
#------------------------------------
# --- 関数定義 ---
usage() {
echo "使用方法: ${SCRIPT_NAME}"
echo " wp-content ディレクトリをバックアップし、古いファイルを整理します。"
exit 0
}
log() {
local message="$1"
echo "$(date '+%Y-%m-%d %H:%M:%S') ${message}" | tee -a "${WP_LOG}"
}
failed() {
echo "エラー: $1" >&2
log "ERROR: $1"
exit 1
}
# バックアップファイル名を生成する(同名ファイルがあれば連番を付加)
make_filename() {
local date_str
date_str=$(date '+%Y%m%d')
local basename="-Wp-content.tar.gz"
local filename="${date_str}${basename}"
local i=1
while [[ -e "${BACKUP_DIR}/${filename}" ]]; do
filename="${date_str}-${i}${basename}"
(( i++ )) || true
done
echo "${filename}"
}
# --- ヘルプ ---
if [[ "${1:-}" == "-?" || "${1:-}" == "-h" || "${1:-}" == "--help" ]]; then
usage
fi
# --- 事前チェック ---
[[ -d "${BACKUP_DIR}" ]] || failed "バックアップ先が見つかりません: ${BACKUP_DIR}"
[[ -d "${BACKUP_SOURCE_DIR}" ]] || failed "バックアップ元が見つかりません: ${BACKUP_SOURCE_DIR}"
[[ -x "${TIDY_UP_SCRIPT}" ]] || failed "整理スクリプトが見つかりません: ${TIDY_UP_SCRIPT}"
# --- ファイル名決定 ---
FILENAME=$(make_filename)
DEST="${BACKUP_DIR}/${FILENAME}"
# --- バックアップ実行 ---
log "WordPress バックアップ開始:"
log "${BACKUP_SOURCE_DIR} → ${DEST}"
echo "WordPress Backup Starting..."
#echo "バックアップファイル:${DEST}"
#echo "sudo chown ${USER}: ${DEST}"
#exit 1
if sudo tar \
--create \
--gzip \
--file="${DEST}" \
"${BACKUP_SOURCE_DIR}"; then # \
#2>> "${WP_LOG}"; then
echo "バックアップファイル:${DEST}"
echo "sudo chown ${USER}: ${DEST}"
sudo chown ${USER}: ${DEST}
log "バックアップ成功: ${FILENAME} ($(du -sh "${DEST}" | cut -f1))"
else
failed "tar コマンドが失敗しました"
fi
# --- 古いファイルの整理 ---
log "古いバックアップを整理します(${DAYS_AGO} 日以前)"
"${TIDY_UP_SCRIPT}" "${BACKUP_DIR}" "${DAYS_AGO}"
log "WordPress バックアップ完了"
echo "WordPress Backup Complete."
Wp-Restore.sh : データベース&WordPressコンテンツの復元
#!/bin/bash
# WoredPress の復元
# データベース(Mysql)とサーバーデータ(wp-content)
# Wp-Restore.sh 2026/05 by Kazuban
#------------------------------------
#--- debug mode, set "DEBUG=1". -----
export DEBUG=
#------------------------------------
export CALLER_SCRIPT="$0"
#export SCRIPT_DIR=$(dirname "$(realpath "$0")")
SCRIPT_DIR=$(dirname "$(readlink -f "${BASH_SOURCE[0]}")")
export SCRIPT_DIR
#------------------------------------
source "${SCRIPT_DIR}/Header.sh"
source "${SCRIPT_DIR}/WordPress_Config_Data.sh"
export BACKUP_DIR="${USER_DIR}/Backup/WordPress/${SUB_DIR}"
#---- MariaDB -----------------------
export MYSQL_RESTORE_SCRIPT="${SCRIPT_DIR}/MariaDB_Restore.sh"
export PRE_BACKUP_FILE="Pre-Backup.bak"
#---- WordPress ---------------------
export WP_RESTORE_SCRIPT="${SCRIPT_DIR}/Wp-Content_Restore.sh"
#------------------------------------
export PRE_BACKUP="Y" # リストア前に現行 wp-content を退避するか Y/N
#----- 関数定義 -----------------------
#user_dir=$(pwd)
#echo $user_dir
# スクリプト終了時に実行させたい場合はここで再定義
cleanup() {
# echo "Wp-Backup 終了処理"
:
}
check_backup_dir(){
if [ ! -d $BACKUP_DIR ]; then
echo "バックアップディレクトリがありません!"
exit 0
fi
}
cmd_mariadb() { check_backup_dir; $MYSQL_RESTORE_SCRIPT; }
cmd_wordpress() { check_backup_dir; $WP_RESTORE_SCRIPT; }
cmd_all() { cmd_mariadb; cmd_wordpress; }
cmd_help() {
echo "--- WordPress Restor Script ---"
echo "Directory: ${SCRIPT_DIR}"
echo "Usage: $0 {db|wp|all|help}"
echo " db = データベース(MariaDB)"
echo " wp = Word Press (Wp-Content)"
echo " all = db + wp"
echo " help = オプション"
}
#----- メインプログラム -------------
#------------------------------------
case "${1:-}" in
db) cmd_mariadb ;;
wp) cmd_wordpress ;;
all) cmd_all ;;
help|"") cmd_help ;;
*)
echo "Unknown command: $1"
cmd_help
exit 1
;;
esac
MariaDB_Restore.sh データベース復元(Wp-Restore.shから呼ばれる)
#!/bin/bash
# WoredPress のデータベース復元スクリプト
# MariaDB_Restore.sh 2026/05 by Kazuban
#------------------------------------
# 直接実行ガード(呼び出し元スクリプトからのみ実行可)
if [[ -z "${CALLER_SCRIPT:-}" ]]; then
echo "直接実行はできません。"
echo "[WP-Backup.sh db] から呼び出してください。"
exit 1
fi
# --- debug mode: DEBUG=1 で有効 ---
#DEBUG=
PRE_BACKUP="Y" # リストア前にバックアップを取るか Y/N
PRE_BACKUP_FILE="Pre-Backup.bak"
#------------------------------------
export SCRIPT_DIR=$(dirname "$(realpath "$0")")
#------------------------------------
source "${SCRIPT_DIR}/Header.sh"
source "${SCRIPT_DIR}/WordPress_Config_Data.sh"
#export BACKUP_DIR="${USER_DIR}/Backup/WordPress/${SUB_DIR}"
#------------------------------------
# ---- 関数定義 ---------------------------------------
# バックアップファイルの一覧を配列に格納する
load_backup_files() {
BACKUP_FILES=()
while IFS= read -r f; do
BACKUP_FILES+=("$(basename "$f")")
#done < <(find "${BACKUP_DIR}" -maxdepth 1 -name "*.bak" | sort)
done < <(find "${BACKUP_DIR}" -maxdepth 1 -name "*-MariaDB.bak" | sort)
}
# 番号付きリストを表示する
list_backups() {
echo "--------------------"
echo "バックアップディレクトリ: ${BACKUP_DIR}"
echo "--------------------"
# --- # は個数を表し、[@] は配列のすべての要素
if [[ ${#BACKUP_FILES[@]} -eq 0 ]]; then
echo "(バックアップファイルが見つかりません)"
else
local i=1
for f in "${BACKUP_FILES[@]}"; do
printf " [%d] %s\n" "$i" "$f"
(( i++ )) || true # set -e 対策: (( )) は 0 になると終了コード 1 を返すため
done
fi
echo "--------------------"
}
# 入力値(番号 or ファイル名)からファイル名を解決して返す
resolve_input() {
local input="$1"
# 数字のみ → 番号として解釈
if [[ "$input" =~ ^[0-9]+$ ]]; then
local idx=$(( input - 1 ))
if (( idx < 0 || idx >= ${#BACKUP_FILES[@]} )); then
echo "エラー: 番号 ${input} は範囲外です(1〜${#BACKUP_FILES[@]})" >&2
exit 1
fi
echo "${BACKUP_FILES[$idx]}"
else
# 文字列 → ファイル名として解釈(リスト内に存在するか確認)
local f
for f in "${BACKUP_FILES[@]}"; do
if [[ "$f" == "$input" ]]; then
echo "$f"
return
fi
done
echo "エラー: ファイルが見つかりません: ${input}" >&2
exit 1
fi
}
# 対話形式でファイルを選択させる
select_backup_file() {
local selected=""
while [[ -z "$selected" ]]; do
read -r -p "番号またはファイル名を入力してください (q で終了): " INPUT
case "$INPUT" in
[qQ])
kill -USR1 $$ # 親プロセス(スクリプト自身)にシグナルを送る
exit 1;;
"") echo "入力してください" ;;
*) selected=$(resolve_input "$INPUT") ;;
esac
done
echo "$selected"
}
usage() {
echo "使い方: $(basename "$0") [バックアップファイル名 or 番号]"
echo " 引数なしで起動すると対話形式で選択できます。"
echo "--------------------"
list_backups
exit 1
}
run_pre_backup() {
local date_str
date_str=$(date '+%Y%m%d-%H%M')
local pre_backup_path="${BACKUP_DIR}/${date_str}-${PRE_BACKUP_FILE}"
echo "--------------------"
echo "-- 事前バックアップを開始します... --"
#mysqldump \
mariadb-dump \
--user="${MYSQL_USER}" \
--password="${MYSQL_USER_PASSWD}" \
--host=localhost \
--all-databases \
--single-transaction \
--quick \
> "${pre_backup_path}"
echo "-- 事前バックアップ完了: ${pre_backup_path} --"
echo "--------------------"
}
run_restore() {
local backup_file="${BACKUP_DIR}/${1}"
echo "--------------------"
echo "-- リストア対象: ${1} --"
echo "-- データベース: ${DATABASE} --"
echo "--------------------"
read -r -p "リストアを実行しますか? (y/n): " YN
case "${YN}" in
[yY])
echo "-- リストアを開始します... --"
#mysql \
mariadb \
--user=root \
--password="${MYSQL_ROOT_PASSWD}" \
"${DATABASE}" \
< "${backup_file}"
echo "-- リストア完了 --"
;;
[nN])
kill -USR1 $$ # 親プロセス(スクリプト自身)にシグナルを送る
exit 0
echo "-- 中止しました --"
exit 0
;;
*)
echo "エラー: y または n を入力してください" >&2
exit 1
;;
esac
}
# ----- メイン処理 --------------------------------------------
# バックアップディレクトリの存在確認
if [[ ! -d "${BACKUP_DIR}" ]]; then
echo "エラー: バックアップディレクトリが存在しません: ${BACKUP_DIR}" >&2
exit 1
fi
# ファイル一覧をグローバル配列に読み込む
# declare 変数の属性やタイプ -a 「配列(Array)」
declare -a BACKUP_FILES
load_backup_files
# ヘルプ
if [[ "${1:-}" == "-h" || "${1:-}" == "--help" ]]; then
usage
fi
# ファイル選択:引数あり → 解決、なし → 対話形式
if [[ $# -gt 0 ]]; then
list_backups
SELECTED_FILE=$(resolve_input "$1")
else
list_backups
SELECTED_FILE=$(select_backup_file)
fi
echo "-- 選択されたファイル: ${SELECTED_FILE} --"
# 事前バックアップ
if [[ "${PRE_BACKUP}" =~ ^[Yy]$ ]]; then
run_pre_backup
fi
# リストア実行
run_restore "${SELECTED_FILE}"
Wp-Content_Restore.sh: WordPressコンテンツ復元(Wp-Restore.shから呼ばれる)
#!/bin/bash
# wp-content ディレクトリの復元スクリプト
# WP-Content_Restore.sh 2026/05 by Kazuban
#------------------------------------
# 直接実行ガード(呼び出し元スクリプトからのみ実行可)
if [[ -z "${CALLER_SCRIPT:-}" ]]; then
echo "直接実行はできません。"
echo "[WP-Backup.sh db] から呼び出してください。"
exit 1
fi
# --- debug mode: DEBUG=1 で有効 ---
#export DEBUG=
PRE_BACKUP="Y" # リストア前に現行 wp-content を退避するか Y/N
#------------------------------------
export SCRIPT_DIR=$(dirname "$(realpath "$0")")
#------------------------------------
source "${SCRIPT_DIR}/Header.sh"
source "${SCRIPT_DIR}/WordPress_Config_Data.sh"
#------------------------------------
# --- 関数定義 ---
# バックアップファイルの一覧を配列に格納する
load_backup_files() {
BACKUP_FILES=()
cmd="find ${BACKUP_DIR} -maxdepth 1 -name *-${WP_CONTENT_DIR}.tar.gz" #${WP_CONTENT_DIR}
while IFS= read -r f; do
BACKUP_FILES+=("$(basename "$f")")
done < <(find "${BACKUP_DIR}" -maxdepth 1 -name "*-${WP_CONTENT_FILENAME}.tar.gz" | sort)
}
# 番号付きリストを表示する
list_backups() {
echo "--------------------"
echo "バックアップディレクトリ: ${BACKUP_DIR}"
echo "--------------------"
if [[ ${#BACKUP_FILES[@]} -eq 0 ]]; then
echo "(バックアップファイルが見つかりません)" >&2
else
local i=1
for f in "${BACKUP_FILES[@]}"; do
printf " [%d] %s\n" "$i" "$f"
(( i++ )) || true # set -e 対策: (( )) は 0 になると終了コード 1 を返すため
done
fi
echo "--------------------"
}
# 入力値(番号 or ファイル名)からファイル名を解決して返す
resolve_input() {
local input="$1"
# 数字のみ → 番号として解釈
if [[ "$input" =~ ^[0-9]+$ ]]; then
local idx=$(( input - 1 ))
if (( idx < 0 || idx >= ${#BACKUP_FILES[@]} )); then
echo "エラー: 番号 ${input} は範囲外です(1〜${#BACKUP_FILES[@]})" >&2
exit 1
fi
echo "${BACKUP_FILES[$idx]}"
else
# 文字列 → ファイル名として解釈(リスト内に存在するか確認)
local f
for f in "${BACKUP_FILES[@]}"; do
if [[ "$f" == "$input" ]]; then
echo "$f"
return
fi
done
echo "エラー: ファイルが見つかりません: ${input}" >&2
exit 1
fi
}
# 対話形式でファイルを選択させる
select_backup_file() {
local selected=""
while [[ -z "$selected" ]]; do
read -r -p "番号またはファイル名を入力してください (q で終了): " INPUT
case "$INPUT" in
[qQ])
kill -USR1 $$
exit 1 ;;
"") echo "入力してください" ;;
*) selected=$(resolve_input "$INPUT") ;;
esac
done
echo "$selected"
}
# 使い方表示
usage() {
echo "使い方: $(basename "$0") [バックアップファイル名 or 番号]"
echo " 引数なしで起動すると対話形式で選択できます。"
echo "--------------------"
list_backups
exit 1
}
# 既存 wp-content を日付付きディレクトリ名にリネームして退避する
run_pre_backup() {
local date_str
date_str=$(date '+%Y%m%d-%H%M')
local backup_path="${WP_CONTENT_PATH}-${date_str}.bak"
echo "--------------------"
echo "-- 事前バックアップ(退避)を開始します... --"
echo "-- ${WP_CONTENT_PATH} → ${backup_path} --"
sudo mv "${WP_CONTENT_PATH}" "${backup_path}"
echo "-- 事前バックアップ完了 --"
echo "--------------------"
}
# リストア実行
run_restore() {
local backup_file="${BACKUP_DIR}/$1"
local work_dir
#work_dir=$(mktemp -d) #添付ディレクトリの利用
work_dir=$BACKUP_DIR
echo "--------------------"
echo "-- リストア対象: $1 --"
echo "-- 展開先 (${WP_CONTENT_DIR}): ${WP_CONTENT_PATH} --"
echo "--------------------"
read -r -p "リストアを実行しますか? (y/n): " YN
case "${YN}" in
[yY])
echo "-- リストアを開始します... --"
# 1. アーカイブ内の wp-content の階層数を確認
echo "-- 展開中: ${backup_file} --"
local wp_path strip_count
list=$(tar tzf "${backup_file}")
wp_path=$(echo "$list" | grep -m1 "${WP_CONTENT_DIR}/$" || true)
echo "------ $wp_path --------"
if [[ -z "${wp_path}" ]]; then
echo "エラー: アーカイブ内に ${WP_CONTENT_DIR} ディレクトリが見つかりません" >&2
exit 1
fi
# パスの / の数から除去する階層数を算出
# 例: home/www/html/sweb01/wp-content/ → スラッシュ5個 → strip=4
strip_count=$(echo "${wp_path}" | tr -cd '/' | wc -c)
strip_count=$(( strip_count - 1 ))
echo $strip_count
#exit 1
if [[ $strip_count < 0 ]]; then
echo "エラー: 階層がありません" >&2
#echo "エラー: アーカイブ内に wp-content ディレクトリが見つかりません"
exit 1
fi
#DIR="${work_dir}/wp-content"
DIR=${work_dir}
echo "${DIR}がない場合には作成します"
mkdir -p "$DIR"
# --strip-components で wp-content/ を作業ディレクトリ直下に展開
tar xvzf "${backup_file}" -C "${DIR}" \
--strip-components="${strip_count}"
ls -la $DIR
# 所定の場所に配置してオーナーを設定
echo sudo mv "${work_dir}/${WP_CONTENT_DIR}" "${WP_CONTENT_PATH}"
echo sudo chown -R "${WP_CONTENT_OWNER}" "${WP_CONTENT_PATH}/"
sudo mv "${work_dir}/${WP_CONTENT_DIR}" "${WP_CONTENT_PATH}"
sudo chown -R "${WP_CONTENT_OWNER}" "${WP_CONTENT_PATH}/"
echo "-- リストア完了 --"
# スクリプト終了時に作業ディレクトリを削除
#trap 'rm -rf "${work_dir}"' EXIT
;;
[nN])
kill -USR1 $$
exit 0
;;
*)
echo "エラー: y または n を入力してください" >&2
exit 1
;;
esac
}
cleanup() {
echo Clean up!!
echo ${BACKUP_DIR}
#read -r -p "${BACKUP_DIR}/${WP_CONTENT_DIR} 削除しますか? (Y/N): " INPUT
# case "$INPUT" in
# [Yy])
# rm -rf "${BACKUP_DIR}/${WP_CONTENT_DIR}"
# esac
}
# --- メイン処理 ---
# バックアップディレクトリの存在確認
if [[ ! -d "${BACKUP_DIR}" ]]; then
echo "エラー: バックアップディレクトリが存在しません: ${BACKUP_DIR}" >&2
exit 1
fi
# ファイル一覧をグローバル配列に読み込む
declare -a BACKUP_FILES
load_backup_files
# ヘルプ
if [[ "${1:-}" == "-h" || "${1:-}" == "--help" ]]; then
usage
fi
# ファイル選択:引数あり → 解決、なし → 対話形式
if [[ $# -gt 0 ]]; then
list_backups
SELECTED_FILE=$(resolve_input "$1")
else
list_backups
SELECTED_FILE=$(select_backup_file)
fi
echo "-- 選択されたファイル: ${SELECTED_FILE} --"
# 事前バックアップ(現行 wp-content の退避)
if [[ "${PRE_BACKUP}" =~ ^[Yy]$ ]]; then
run_pre_backup
fi
# リストア実行
run_restore "${SELECTED_FILE}"
Header.sh : デバッグモード仕様(変数 DEBUG=1 で有効)
#!/bin/bash
#
# Header.sh 2026/05 by AI & Kazuban
# 共通ヘッダー: source で読み込んで使う
# 使い方: source "${SCRIPT_DIR}/Header.sh"
#
#------------------------------------
#-e:失敗で停止:#-u:未定義変数禁止:#pipefail:パイプの途中も検知
set -euo pipefail
# --- traps ---
trap 'echo "-- 中止しました --"; exit 0' USR1
trap 'echo "Error at line $LINENO"; exit 1' ERR
trap cleanup EXIT
# cleanup は呼び出し元スクリプトで上書き可能
cleanup() {
:
}
# --- debug mode: DEBUG=1 で有効 ---
export DEBUG=${DEBUG:-0}
if [[ "$DEBUG" == "1" ]]; then
echo "Debug mode is 'true' !! "
export PS4='+ ${LINENO}: '
set -x
trap 'read -p "STEP> " < /dev/tty' DEBUG
else
echo "Debug mode is 'false' !! "
fi
Tidyup_backfile.sh : バックアップファイルの整理(引数:対象ディレクトリ・保存日数)
#!/bin/bash
# Delete $DAY days ago from backup
#
# Tidyup_backfile.sh by AI & Kazuban 2026/05
# default 10 days ago
#
#------------------------
# delete_backup - バックアップファイルを整理するスクリプト
# 使用方法: delete_backup [削除対象ディレクトリ] [何日前まで残すか]
#set -euo pipefail
#--- for debag ----------------------
#--- デバッグモード(DEBUG=1 で有効)---
#if [[ "${DEBUG:-0}" == "1" ]]; then
# export PS4='+ ${LINENO}: '
# set -x
# trap 'read -p "STEP> " < /dev/tty' DEBUG
#fi
readonly SCRIPT_NAME="$(basename "$0")"
usage() {
echo "使用方法: ${SCRIPT_NAME} <削除対象ディレクトリ> [保持日数]"
echo " 削除対象ディレクトリ : バックアップファイルのあるディレクトリ"
echo " 保持日数 : 何日前までのファイルを残すか (デフォルト: 10)"
exit 1
}
# --- 引数チェック ---
if [[ $# -lt 1 || "$1" == "-?" || "$1" == "-h" || "$1" == "--help" ]]; then
usage
fi
TARGET_DIR="$1"
DAYS="${2:-10}"
# --- 数値チェック ---
if ! [[ "$DAYS" =~ ^[0-9]+$ ]]; then
echo "エラー: 保持日数には正の整数を指定してください: ${DAYS}" >&2
exit 1
fi
# --- ディレクトリ存在チェック ---
if [[ ! -d "$TARGET_DIR" ]]; then
echo "エラー: ディレクトリが見つかりません: ${TARGET_DIR}" >&2
exit 1
fi
# --- 削除基準日を算出 ---
DEL_DATE="$(date --date="${DAYS} days ago" +%Y%m%d)"
echo "削除基準日: ${DEL_DATE} より前のファイルを削除します (保持日数: ${DAYS}日)"
# --- 対象ファイルの処理 ---
# 数字始まりのファイル名から先頭8桁(YYYYMMDD)を取得して重複排除
while IFS= read -r file_date; do
if [[ "$file_date" < "$DEL_DATE" ]]; then
echo "削除: ${TARGET_DIR}/${file_date}*"
rm -f -- "${TARGET_DIR}/${file_date}"*
fi
done < <(
ls -- "$TARGET_DIR" \
| grep -E '^[0-9]' \
| awk '{ print substr($0, 1, 8) }' \
| sort -u
)
echo "完了"
自動バックアップ
こちらでも、紹介していますが、「crontab」に下記のように設定する事で、毎日2時に自動バックアップできるようになります
00 2 * * * /home/kazuban/Backup/bin/Wp-Backup.sh all

コメント