- 新增 backend/auvops.sh:容器内直接执行的统一运维工具 (cache-clear/clean-expired/cache-count/recollect/sh/help) - heredoc传python代码,日期等参数走环境变量防注入 - 后续运维操作收敛到该文件,加 cmd_xxx + case 注册一行即可 - 删除 recollect-daily.sh,其能力并入 auvops.sh recollect Co-Authored-By: Claude <noreply@anthropic.com>
151 lines
4.2 KiB
Bash
Executable File
151 lines
4.2 KiB
Bash
Executable File
#!/usr/bin/env bash
|
||
# auvops.sh - AUV 容器内运维工具(在容器内直接执行,非宿主机 docker exec)
|
||
#
|
||
# 拷贝进容器 /app(backend 根)后运行。后续新增运维能力都收敛到这个文件:
|
||
# 加一个 cmd_xxx 函数 + 在 main 的 case 里注册一行即可。
|
||
#
|
||
# 用法(容器内):
|
||
# ./auvops.sh cache-clear # 清空全部缓存(当日数据全新)
|
||
# ./auvops.sh clean-expired # 只清理已过期的缓存
|
||
# ./auvops.sh cache-count # 查看缓存条数
|
||
# ./auvops.sh recollect [DATE] # 删除并重采指定交易日(默认当天)
|
||
# ./auvops.sh sh # 进入交互式 shell
|
||
# ./auvops.sh help # 查看帮助
|
||
#
|
||
# 依赖: 容器内 python 可用(能 import services.*),工作目录自动切到脚本所在目录。
|
||
#
|
||
# 示例:
|
||
# ./auvops.sh cache-clear
|
||
# ./auvops.sh recollect 2026-08-10
|
||
# ./auvops.sh cache-count
|
||
|
||
set -euo pipefail
|
||
|
||
# 容器内 backend 根:脚本所在目录(/app)
|
||
ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||
cd "${ROOT}"
|
||
|
||
# 容器内用 python;本机验证时可 PY=./venv/bin/python ./auvops.sh ...
|
||
PY="${PY:-python}"
|
||
"${PY}" -c "import services" >/dev/null 2>&1 || {
|
||
echo "❌ 无法在 ${ROOT} 下 import services(确认已在容器内 /app 且 python 可用)" >&2
|
||
exit 1
|
||
}
|
||
|
||
# 在容器内跑 python 代码。日期等参数通过环境变量传,避免拼接进代码字符串。
|
||
# 用法: py_env "KEY1=val1" "KEY2=val2" <<'EOF'
|
||
# <python 代码>
|
||
# EOF
|
||
py_env() {
|
||
local env_args=()
|
||
while [[ "$#" -gt 0 ]]; do
|
||
env_args+=("${1%%=*}=${1#*=}"); shift
|
||
done
|
||
env "${env_args[@]}" "${PY}" -
|
||
}
|
||
|
||
# ---- 子命令实现 ----
|
||
|
||
# 清空全部缓存(当日数据全新)
|
||
cmd_cache_clear() {
|
||
echo "① 清空全部缓存"
|
||
"${PY}" - <<'EOF'
|
||
from services.cache import clear_all
|
||
clear_all()
|
||
print(" cache 表已清空")
|
||
EOF
|
||
echo "✅ 缓存已清空"
|
||
}
|
||
|
||
# 只清理已过期缓存
|
||
cmd_clean_expired() {
|
||
echo "① 清理过期缓存"
|
||
"${PY}" - <<'EOF'
|
||
from services.cache import clean_expired
|
||
clean_expired()
|
||
print(" 过期缓存已清理")
|
||
EOF
|
||
echo "✅ 完成"
|
||
}
|
||
|
||
# 查看缓存条数
|
||
cmd_cache_count() {
|
||
"${PY}" - <<'EOF'
|
||
from database import get_connection
|
||
conn = get_connection()
|
||
try:
|
||
n = conn.execute("SELECT COUNT(*) FROM cache").fetchone()[0]
|
||
print(f"缓存条数: {n}")
|
||
finally:
|
||
conn.close()
|
||
EOF
|
||
}
|
||
|
||
# 删除指定交易日旧数据,并用新选股逻辑重新采集入库
|
||
cmd_recollect() {
|
||
local date="${1:-$(date +%F)}"
|
||
if ! [[ "${date}" =~ ^[0-9]{4}-[0-9]{2}-[0-9]{2}$ ]]; then
|
||
echo "❌ 日期格式错误:${date}(应为 YYYY-MM-DD)" >&2
|
||
exit 1
|
||
fi
|
||
|
||
echo "================================================"
|
||
echo "🚀 容器: ${HOSTNAME:-unknown} 交易日: ${date}"
|
||
echo "================================================"
|
||
|
||
echo "① 删除 ${date} 旧数据"
|
||
py_env "TARGET_DATE=${date}" <<'EOF'
|
||
import os
|
||
from database import get_connection
|
||
date = os.environ["TARGET_DATE"]
|
||
conn = get_connection()
|
||
try:
|
||
for tbl in ("daily_core_stocks", "daily_core_stock_themes", "daily_top_themes"):
|
||
cur = conn.execute("DELETE FROM " + tbl + " WHERE trade_date = ?", (date,))
|
||
print(f" {tbl}: 删除 {cur.rowcount} 行")
|
||
conn.commit()
|
||
finally:
|
||
conn.close()
|
||
EOF
|
||
|
||
echo "② 用新选股逻辑重采 ${date}"
|
||
py_env "TARGET_DATE=${date}" <<'EOF'
|
||
import asyncio
|
||
import os
|
||
from services.daily_collector import collect_daily
|
||
result = asyncio.run(collect_daily(os.environ["TARGET_DATE"]))
|
||
print(" 结果:", result)
|
||
EOF
|
||
echo "✅ 完成"
|
||
}
|
||
|
||
# 进入交互式 shell
|
||
cmd_sh() {
|
||
"${PY}" || true
|
||
}
|
||
|
||
# 帮助
|
||
usage() {
|
||
awk 'NR >= 2 && /^#/ { sub(/^# ?/, ""); print; next } NR >= 2 && !/^#/ { exit }' "${BASH_SOURCE[0]}"
|
||
}
|
||
|
||
# ---- 入口 ----
|
||
main() {
|
||
if [[ "$#" -eq 0 ]]; then
|
||
usage
|
||
exit 1
|
||
fi
|
||
local cmd="$1"; shift
|
||
case "${cmd}" in
|
||
cache-clear|cc) cmd_cache_clear "$@" ;;
|
||
clean-expired) cmd_clean_expired "$@" ;;
|
||
cache-count) cmd_cache_count "$@" ;;
|
||
recollect) cmd_recollect "$@" ;;
|
||
sh|shell|python) cmd_sh "$@" ;;
|
||
help|-h|--help) usage ;;
|
||
*) echo "❌ 未知命令: ${cmd}(./auvops.sh help 查看用法)" >&2; exit 1 ;;
|
||
esac
|
||
}
|
||
|
||
main "$@"
|