# [メタ情報] # 識別子: Xserver自動ダウンロード_exe # システム名: Xserver自動ダウンロード # 技術種別: Misc # 機能名: Misc # 使用言語: ShellScript plist # 状態: 実行用 # [/メタ情報] 要約:Xserver上では毎日0:30にシェルスクリプトを実行し、xxxxxxxx.com の public_html ディレクトリを対象にZIPバックアップを作成する。wp-content 内の mmedia と pmedia は除外し、不要な .DS_Store は事前に削除した上で、backups/zip_files に保存する。Mac側では launchd により毎日1:00に rsync を起動し、SSH接続でこのZIPファイルをローカルの Library 配下へ同期する。二重起動防止のロック機構、安全な PATH 設定、30分のタイムアウト、詳細なログ出力を備え、処理結果に応じて Mail.app から成功・エラー通知を送信する自動バックアップ運用となっている。 bin/bash/home/xxxxxxxx/xserver_scripts/compress_public_html.sh 毎日0:30 #!/bin/bash # --- PATH(cron 実行時のために必ず設定) --- export PATH="/usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin" # --- 基本ディレクトリ設定 --- BASE_DIR="/home/xxxxxxxx/xxxxxxxx.com" SOURCE_DIR="public_html" # --- 出力フォルダと zip ファイル名 --- OUTPUT_FOLDER="${BASE_DIR}/backups/zip_files" OUTPUT_FILE="${OUTPUT_FOLDER}/zip_public_html.zip" # --- 出力フォルダが無ければ作成 --- mkdir -p "$OUTPUT_FOLDER" # --- public_html の1つ上へ移動 --- cd "$BASE_DIR" || exit 1 # --- 不要ファイル(.DS_Store)削除(任意) --- find "$SOURCE_DIR" -name ".DS_Store" -delete # --- ZIP 作成(mmedia / pmedia のみ除外) --- zip -r "$OUTPUT_FILE" "$SOURCE_DIR" \ -x "public_html/wp-content/mmedia/*" \ -x "public_html/wp-content/pmedia/*" \ -x "*/.DS_Store" # --- 結果表示 --- if [ $? -eq 0 ]; then echo "フォルダを正常に圧縮しました: $OUTPUT_FILE" else echo "圧縮に失敗しました。" fi /Users/xxxxxxxxm1/scripts/sync_xserver_wp_backups_zip.sh #!/bin/bash set -u # ===== launchd で動かす前提の安全な PATH ===== export PATH="/opt/homebrew/bin:/usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin" export LANG="en_US.UTF-8" # ===== ログ ===== LOG_DIR="$HOME/scripts/logs" mkdir -p "$LOG_DIR" LOG_FILE="$LOG_DIR/rsync_zip_files_public_html.log" # ===== ロック(二重起動防止)===== LOCKDIR="/tmp/rsync_zip_files_public_html.lock" if ! mkdir "$LOCKDIR" 2>/dev/null; then echo "[$(date '+%F %T')] already running -> exit" >> "$LOG_FILE" exit 0 fi trap 'rmdir "$LOCKDIR" 2>/dev/null || true' EXIT # ===== SSH情報 ===== SSH_HOST="xxxxxxxx.xsrv.jp" SSH_PORT="10022" SSH_USER="xxxxxxxx" REMOTE_PATH="/home/xxxxxxxx/xxxxxxxx.com/backups/zip_files" # ===== 保存先(Finder負荷を避けるため Library 配下へ)===== # 既に作った: /Users/xxxxxxxxm1/Library/Xserver_dl/ LOCAL_BASE="$HOME/Library/Xserver_dl" LOCAL_PATH="$LOCAL_BASE/zip_files" # ===== 事前チェック(ローカル側)===== if [[ ! -d "$LOCAL_PATH" ]]; then mkdir -p "$LOCAL_PATH" || { echo "[$(date '+%F %T')] mkdir failed: $LOCAL_PATH" >> "$LOG_FILE" exit 3 } fi # ===== rsync ===== RSYNC_BIN="$(command -v rsync || true)" if [[ -z "$RSYNC_BIN" ]]; then echo "[$(date '+%F %T')] rsync not found" >> "$LOG_FILE" exit 4 fi # ===== タイムアウト ===== # coreutils を入れていれば gtimeout がある。無ければ timeout はスキップ。 TIMEOUT_BIN="$(command -v gtimeout || true)" TIMEOUT_SEC=1800 # 30分 # ===== ssh オプション(rsync -e に渡す文字列を安全に組み立て)===== SSH_CMD="ssh -p ${SSH_PORT} -o BatchMode=yes -o ServerAliveInterval=30 -o ServerAliveCountMax=4 -o ConnectTimeout=15" echo "[$(date '+%F %T')] start rsync -> ${SSH_USER}@${SSH_HOST}:${REMOTE_PATH}/ => ${LOCAL_PATH}/" >> "$LOG_FILE" CMD=( "$RSYNC_BIN" -avz --partial -e "$SSH_CMD" \ "${SSH_USER}@${SSH_HOST}:${REMOTE_PATH}/" \ "${LOCAL_PATH}/" ) if [[ -n "$TIMEOUT_BIN" ]]; then "$TIMEOUT_BIN" "$TIMEOUT_SEC" "${CMD[@]}" >> "$LOG_FILE" 2>&1 else "${CMD[@]}" >> "$LOG_FILE" 2>&1 fi RSYNC_STATUS=$? echo "[$(date '+%F %T')] rsync exit=$RSYNC_STATUS" >> "$LOG_FILE" # ===== Mail 通知(必ずログに残す)===== MAIL_TO="bbbbbbbb.yyyyyyyy@gmail.com" MAIL_TIMEOUT_SEC=180 # 必要なら 300 などに増やす if [[ $RSYNC_STATUS -eq 0 ]]; then /usr/bin/osascript <> "$LOG_FILE" 2>&1 with timeout of ${MAIL_TIMEOUT_SEC} seconds tell application "Mail" set m to make new outgoing message with properties {subject:"rsync_zip_files_public_html 完了通知", content:"rsync_public_htmlが正常に完了しました。", visible:false} tell m make new to recipient at end of to recipients with properties {address:"${MAIL_TO}"} send end tell end tell end timeout EOF OSASCRIPT_STATUS=$? echo "[$(date '+%F %T')] osascript exit=${OSASCRIPT_STATUS} success-mail" >> "$LOG_FILE" else /usr/bin/osascript <> "$LOG_FILE" 2>&1 with timeout of ${MAIL_TIMEOUT_SEC} seconds tell application "Mail" set m to make new outgoing message with properties {subject:"rsync_zip_files_public_html エラー通知", content:"rsync_public_htmlがエラーで終了しました。ステータスコード: ${RSYNC_STATUS}", visible:false} tell m make new to recipient at end of to recipients with properties {address:"${MAIL_TO}"} send end tell end tell end timeout EOF OSASCRIPT_STATUS=$? echo "[$(date '+%F %T')] osascript exit=${OSASCRIPT_STATUS} error-mail" >> "$LOG_FILE" fi exit "$RSYNC_STATUS" /Users/xxxxxxxxm1/Library/LaunchAgents/com.xxxxxxxx.sync_xserver_wp_backups_zip.plist Label com.xxxxxxxx.sync_xserver_wp_backups_zip ProgramArguments /bin/bash /Users/xxxxxxxxm1/scripts/sync_xserver_wp_backups_zip.sh StartCalendarInterval Hour1 Minute0 StandardOutPath /Users/xxxxxxxxm1/scripts/logs/sync_xserver_wp_backups_zip.out StandardErrorPath /Users/xxxxxxxxm1/scripts/logs/sync_xserver_wp_backups_zip.err RunAtLoad