chagitqskjdlqskdmslkqdj chatjkqsdjlqskdjqslkdjkslqd azekzkjeqksldjlqsjdlsqd xqlqkzdjlqsdklqsdkslqd
?? Go up: /opt
#!/bin/bash
# ============================================================
# WP-CLI実行スクリプト
#
# [使用方法]
# /opt/sh/wp_cli/wp_cli.sh "PHP_VERSION" "WP_PATH" "WP_COMMAND"
#
# [引数]
# - PHP_VERSION: PHPのバージョン(例: 8.2)
# - WP_PATH: WordPressのディレクトリパス(例: /home/user001/example.com/public_html/)
# - WP_COMMAND: WP-CLIのコマンド(例: core install)
#
# [補足]
# - cpadmin(WebAPI)がsudoでユーザー権限で実行します(ユーザーが直接実行することはできません)
# - ホワイトリスト(ALLOWED_COMMANDS)で許可されていないコマンドは実行できません
# ============================================================
# ============================================================
# 事前準備(引数取得、エラーハンドリング)
# ============================================================
# エラーハンドリングの強化
set -euo pipefail
# 許可されたWP-CLIコマンドのリスト
ALLOWED_COMMANDS=(
"core"
"plugin"
"theme"
"user"
"db"
"export"
"import"
"maintenance-mode"
"config"
"rewrite"
"cache"
"cron"
"search-replace"
"option"
"site"
"network"
"role"
"widget"
"sidebar"
"taxonomy"
"term"
"comment-meta"
"post-meta"
"user-meta"
"rest"
"scaffold"
"package"
"doctor"
"post"
"comment"
"eval-file" # 当社管理の定型スクリプト実行のみなので許可
"transient"
"media"
"i18n"
"cldsec-wp-security" # CloudSecure WP Security
"super-cache" # WP Super Cache
"w3-total-cache" # W3 Total Cache
"litespeed-purge" # LiteSpeed Cache
"rocket" # WP Rocket
"wc" # WooCommerce
"yoast" # Yoast SEO
"rankmath" # Rank Math
)
# wp-cliバイナリのパス設定
## /usr/bin/wp-cliが存在しない場合は/usr/bin/wpを実行
if [[ -f "/usr/bin/wp-cli" ]]; then
WP_CLI_PATH="/usr/bin/wp-cli"
else
WP_CLI_PATH="/usr/bin/wp"
fi
# 引数チェック
if [ $# -ne 3 ]; then
echo "エラー: 引数が正しくありません。"
echo "使用方法: $0 \"PHPバージョン\" \"WordPressディレクトリパス\" \"WP-CLIコマンド\""
exit 1
fi
PHP_VERSION="$1"
WP_PATH="$2"
WP_COMMAND="$3"
# ============================================================
# 入力値サニタイゼーション関数
# ============================================================
# パスの安全性チェック関数
validate_path() {
local path="$1"
# 異常に長いパスの拒否
if [ ${#path} -gt 4096 ]; then
echo "エラー: パスが長すぎます(最大4096文字)"
return 1
fi
# 危険な文字をチェック
if [[ "$path" =~ [\;\|\&\$\`\\\(\)\{\}\[\]\<\>] ]]; then
echo "エラー: パスに危険な文字が含まれています: $path" >&2
return 1
fi
# その他NG文字列チェック
local dangerous_patterns=(
".." # ディレクトリトラバーサル
"\0" # ヌル文字
"%2e%2e" # URLエンコードされた..
"%00" # URLエンコードされたヌル文字
"//" # ダブルスラッシュ
"%2f%2e%2e" # URLエンコードされた/..
"%2e%2e%2f" # URLエンコードされた../
"%252e%252e" # 二重URLエンコードされた..
"%c0%ae" # UTF-8オーバーロング.
"%c1%9c" # UTF-8オーバーロング\
"~" # ホームディレクトリ参照
)
for pattern in "${dangerous_patterns[@]}"; do
if [[ "$path" == *"$pattern"* ]]; then
echo "エラー: パスに危険なパターンが検出されました: $pattern"
return 1
fi
done
return 0
}
# ============================================================
# PHPバージョンの検証・PHPバイナリのパス構築
# ============================================================
# PHPバージョンの検証
if [[ ! "$PHP_VERSION" =~ ^[0-9]+\.[0-9]+$ ]]; then
echo "エラー: PHPバージョンの形式が正しくありません。(例: 8.2)"
exit 1
fi
# PHPバイナリのパス構築
PHP_BINARY="/opt/php-${PHP_VERSION}/bin/php"
# PHPバイナリの存在確認
if [ ! -f "$PHP_BINARY" ]; then
echo "エラー: PHPバイナリが見つかりません: $PHP_BINARY"
exit 1
fi
# ============================================================
# WP_PATHの正規化・チェック
# ============================================================
# パスの安全性チェック
if ! validate_path "$WP_PATH"; then
exit 1
fi
# realpath を使用してパスを正規化
WP_PATH_REAL=$(realpath "$WP_PATH" 2>/dev/null) || {
echo "エラー: パスの解決に失敗しました。"
exit 1
}
WP_PATH="$WP_PATH_REAL"
# シンボリックリンクチェック
if [ -e "$WP_PATH" ] && [ -L "$WP_PATH" ]; then
echo "エラー: シンボリックリンクが指定されています: $WP_PATH"
exit 1
fi
# WordPressディレクトリの存在確認
if [ ! -d "$WP_PATH" ]; then
echo "エラー: WordPressディレクトリが見つかりません: $WP_PATH"
exit 1
fi
# ディレクトリの読み書き権限確認
if [ ! -r "$WP_PATH" ] || [ ! -w "$WP_PATH" ]; then
echo "エラー: WordPressディレクトリへの適切な権限がありません。"
exit 1
fi
# ============================================================
# 実行ユーザーの検証
# ============================================================
# パスからサーバーIDとドメイン名を抽出
SERVER_ID=$(echo "$WP_PATH" | sed -n 's|^/home/\([^/]*\)/.*|\1|p')
DOMAIN_NAME=$(echo "$WP_PATH" | sed -n 's|^/home/[^/]*/\([^/]*\)/.*|\1|p')
if [ -z "$SERVER_ID" ] || [ -z "$DOMAIN_NAME" ]; then
echo "エラー: サーバーIDまたはドメイン名を抽出できませんでした。"
exit 1
fi
# cpadminからのsudo実行のみ許可
if [ "${SUDO_USER:-}" != "cpadmin" ]; then
echo "エラー: このスクリプトは実行できません。"
exit 1
fi
# SERVER_IDと実行ユーザーが一致するかチェック
if [ "$SERVER_ID" != "$USER" ]; then
echo "エラー: 実行ユーザー($USER)とパスのサーバーID($SERVER_ID)が一致しません。"
echo "指定されたパスは別のユーザーのサイトです。"
exit 1
fi
# システムユーザーかどうかを判定
check_system_user() {
local username="$1"
if [ -z "$username" ]; then
return 0 # システムユーザー(true)
fi
# UIDとGIDを取得
local uid=$(id -u "$username" 2>/dev/null || echo "")
local gid=$(id -g "$username" 2>/dev/null || echo "")
# id コマンドが失敗した場合はシステムユーザーとして扱う
if [ -z "$uid" ] || [ -z "$gid" ]; then
return 0 # システムユーザー(true)
fi
# uidが2000以上の場合、システムユーザではない
if [ "$uid" -ge 2000 ]; then
return 1 # 非システムユーザー(false)
fi
# uidが1000-2000かつgidが1000の場合
if [ "$uid" -ge 1000 ] && [ "$uid" -lt 2000 ] && [ "$gid" -eq 1000 ]; then
# 除外対象のユーザー名リスト
local system_users=("phpmyadmin" "phpmyadmin2" "phpmyadmin4a" "phpmyadmin4b" "webftp" "webmail" "analyzer")
# 除外対象のユーザー名以外の場合はシステムユーザではない
for sys_user in "${system_users[@]}"; do
if [ "$username" = "$sys_user" ]; then
return 0 # システムユーザー(true)
fi
done
return 1 # 非システムユーザー(false)
fi
return 0 # その他の場合はシステムユーザー(true)
}
if check_system_user "$USER"; then
echo "エラー: システムユーザーでは実行できません。"
exit 1
fi
# ============================================================
# WP-CLIコマンドの検証
# ============================================================
# まず「wp」で始まるかチェック
if [[ ! "$WP_COMMAND" =~ ^wp[[:space:]] ]]; then
echo "エラー: コマンドは'wp'で始まる必要があります。"
exit 1
fi
# コマンドの安全性チェック
check_command_safety() {
local cmd="$1"
# NULLバイトチェック
if printf '%s' "$cmd" | od -An -tx1 | grep -q " 00"; then
echo "エラー: コマンドにNULLバイトが含まれています。"
return 1
fi
# 引用符で囲まれていないバッククォートのみを危険として検出
# 単純なパーサーで引用符の状態を追跡
local in_single_quote=false
local in_double_quote=false
local escaped=false
local i=0
while [ $i -lt ${#cmd} ]; do
local char="${cmd:$i:1}"
if [ "$escaped" = true ]; then
escaped=false
elif [ "$char" = "\\" ]; then
escaped=true
elif [ "$char" = "'" ] && [ "$in_double_quote" = false ]; then
in_single_quote=$( [ "$in_single_quote" = true ] && echo false || echo true )
elif [ "$char" = '"' ] && [ "$in_single_quote" = false ]; then
in_double_quote=$( [ "$in_double_quote" = true ] && echo false || echo true )
elif [ "$char" = '`' ] && [ "$in_single_quote" = false ] && [ "$in_double_quote" = false ]; then
echo "エラー: 引用符で囲まれていないバッククォート(\`)は使用できません。"
return 1
fi
i=$((i + 1))
done
# 引用符で囲まれた部分を除去して危険文字をチェック
local temp_cmd="$cmd"
# 引用符で囲まれた部分を一時的に置換
temp_cmd=$(echo "$temp_cmd" | sed 's/"[^"]*"/__QUOTED__/g' | sed "s/'[^']*'/__QUOTED__/g")
if [[ "$temp_cmd" =~ [\|\&\;\<\>] ]]; then
echo "エラー: 危険文字は引用符で囲んでください: | & ; < >"
echo "例: --title=\"含む&文字\""
return 1
fi
return 0
}
# 安全性チェック実行
if ! check_command_safety "$WP_COMMAND"; then
exit 1
fi
# コマンドからwpプレフィックスを除去してコマンド部分を抽出
COMMAND_PART=$(echo "$WP_COMMAND" | sed 's/^wp[[:space:]]*//')
MAIN_COMMAND=$(echo "$COMMAND_PART" | awk '{print $1}')
# 許可されたコマンドかチェック
COMMAND_ALLOWED=false
for allowed in "${ALLOWED_COMMANDS[@]}"; do
if [ "$MAIN_COMMAND" = "$allowed" ]; then
COMMAND_ALLOWED=true
break
fi
done
if [ "$COMMAND_ALLOWED" = false ]; then
echo "エラー: 許可されていないコマンドです: $MAIN_COMMAND"
echo "許可されているコマンド: ${ALLOWED_COMMANDS[*]}"
exit 1
fi
# wp-cliの存在確認
if [ ! -f "$WP_CLI_PATH" ]; then
echo "エラー: WP-CLIが見つかりません: $WP_CLI_PATH"
exit 1
fi
# ============================================================
# WP-CLIコマンドの実行
# ============================================================
# WP-CLIコマンドの実行
cd "$WP_PATH" || {
echo "エラー: WordPressディレクトリに移動できません: $WP_PATH"
exit 1
}
# wp cli実行
eval "$PHP_BINARY" "$WP_CLI_PATH" --path="$WP_PATH" $COMMAND_PART
# 終了
exit $?