#!/usr/bin/env bash # scripts/ppt_cleanup.sh # 由 launchd / cron 呼叫 — 清理 N 天前過期的 PPT 檔 + DB row。 # 安全執行:失敗時不會 raise,只寫 log。 # # 環境變數(皆可在 launchd plist / 命令列覆寫): # PROJECT_DIR source code 根目錄(預設:相對路徑解析至此腳本上層) # VENV_PY python 直譯器(預設:${PROJECT_DIR}/venv/bin/python3,找不到則 fallback python3) # DAYS_OLD 過期門檻天數(預設 7) # DRY_RUN true/false(預設 false—launchd 排程實刪;手動測試請傳 DRY_RUN=true) set -euo pipefail # 動態解析路徑(critic Medium-4 修正):手動執行不再需要設環境變數 SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" PROJECT_DIR="${PROJECT_DIR:-$(cd "$SCRIPT_DIR/.." && pwd)}" # venv python,找不到時 fallback 到系統 python3 DEFAULT_VENV_PY="${PROJECT_DIR}/venv/bin/python3" if [[ -x "$DEFAULT_VENV_PY" ]]; then VENV_PY="${VENV_PY:-$DEFAULT_VENV_PY}" else VENV_PY="${VENV_PY:-python3}" fi LOG_FILE="${LOG_FILE:-${PROJECT_DIR}/logs/ppt_cleanup.log}" DAYS_OLD="${DAYS_OLD:-7}" DRY_RUN="${DRY_RUN:-false}" # 將字串轉為 Python bool literal if [[ "$DRY_RUN" =~ ^(true|TRUE|1|yes|YES)$ ]]; then PY_DRY_RUN="True" else PY_DRY_RUN="False" fi mkdir -p "$(dirname "$LOG_FILE")" cd "$PROJECT_DIR" { echo "[$(date +'%Y-%m-%d %H:%M:%S')] PPT cleanup start (days_old=$DAYS_OLD, dry_run=$PY_DRY_RUN, py=$VENV_PY)" "$VENV_PY" -c " from routes.openclaw_bot_routes import cleanup_expired_ppt_cache import json stat = cleanup_expired_ppt_cache(days_old=$DAYS_OLD, dry_run=$PY_DRY_RUN) print('result:', json.dumps(stat, ensure_ascii=False)) " 2>&1 || echo "[ERROR] cleanup failed" echo "[$(date +'%Y-%m-%d %H:%M:%S')] PPT cleanup end" echo "---" } >> "$LOG_FILE"