#!/usr/bin/env bash # 处置链路部署后自检(L1 停止分发 / L4 整页停用 / CLI 可用性) # # 为什么需要它:本机沙箱起不了 web(无 redis),L1/L4 的 HTTP 行为只能在服务器上验证。 # 这个脚本把「施加处置 → 观察 HTTP → 自动撤销」串起来,避免手工操作忘了解除。 # # 用法: # BASE_URL=https://box-dev.example.com DOMAIN=<测试箱主域名> TAMABOX=/path/to/NekoBox \ # bash dev/devcheck-restrict.sh # 只打印将要执行的命令(dry-run) # # BASE_URL=... DOMAIN=... TAMABOX=... RUN=1 \ # bash dev/devcheck-restrict.sh # 真正执行,结束时自动撤销 # # 注意: # - DOMAIN 必须是**测试箱主**,不要用真实用户;脚本会临时施加 L4/L1 再撤销。 # - 站点默认语言可能是 ja,页面文案断言按日文/英文各查一次,避免误判「没生效」。 # - 只依赖 CLI 与 curl,不需要 psql 凭据。 set -uo pipefail BASE_URL=${BASE_URL:?need BASE_URL, e.g. https://box-dev.example.com} DOMAIN=${DOMAIN:?need DOMAIN, a TEST box domain only} TAMABOX=${TAMABOX:-./NekoBox} RUN=${RUN:-0} DAYS=${DAYS:-1} pass=0 fail=0 restricted=0 say() { printf '%s\n' "$*"; } check() { local name=$1 want=$2 got=$3 if [ "$want" = "$got" ]; then say " PASS $name (=$got)" pass=$((pass + 1)) else say " FAIL $name (want $want, got $got)" fail=$((fail + 1)) fi } code() { curl -s -o /dev/null -w '%{http_code}' --max-time 10 "$1"; } do_restrict() { restricted=1 if [ "$RUN" = 1 ]; then "$TAMABOX" restrict --domain "$DOMAIN" --level "$1" --days "$DAYS" --reason "deploy self-check" --yes else say " [dry-run] $TAMABOX restrict --domain $DOMAIN --level $1 --days $DAYS --reason 'deploy self-check' --yes" fi } cleanup() { if [ "$RUN" = 1 ] && [ "$restricted" = 1 ]; then say "" say "== 兜底撤销(无论中途是否失败)==" "$TAMABOX" unrestrict --domain "$DOMAIN" || true fi } trap cleanup EXIT say "== 0. 二进制是否包含新命令 ==" if "$TAMABOX" --help 2>&1 | grep -q 'restrict'; then say " PASS restrict 命令存在" pass=$((pass + 1)) else say " FAIL 二进制里没有 restrict —— 构建的是旧代码(注意入口是根目录 tamabox.go,或用 ./cmd/)" fail=$((fail + 1)) say "" say "结果: 无法继续,先修构建入口。" exit 1 fi say "" say "== 1. 基线:处置前箱主页应可访问 ==" base=$(code "$BASE_URL/_/$DOMAIN") check "box page before restrict" 200 "$base" say "" say "== 2. L4 整页停用 ==" do_restrict L4 sleep 1 check "box page under L4" 302 "$(code "$BASE_URL/_/$DOMAIN")" check "restricted page" 200 "$(code "$BASE_URL/restricted")" if [ "$RUN" = 1 ]; then body=$(curl -sL --max-time 10 "$BASE_URL/_/$DOMAIN") if printf '%s' "$body" | grep -qE '一時的に利用できません|temporarily unavailable|暫時無法存取|暂时不可访问'; then say " PASS restricted page copy rendered" pass=$((pass + 1)) else say " FAIL restricted page copy not found (检查 i18n 与模板是否部署)" fail=$((fail + 1)) fi else say " [dry-run] 跳过文案断言" fi say "" say "== 3. L1 停止分发:页面恢复、分享卡被拦 ==" do_restrict L1 sleep 1 check "box page under L1" 200 "$(code "$BASE_URL/_/$DOMAIN")" qid=$(curl -s --max-time 10 "$BASE_URL/_/$DOMAIN" | grep -o "/_/$DOMAIN/[0-9]\+" | head -1 | grep -o '[0-9]\+$') if [ -n "${qid:-}" ]; then check "share card under L1 (qid=$qid)" 302 "$(code "$BASE_URL/_/$DOMAIN/$qid/share-card")" else say " SKIP 该箱主没有已公开回答,无法验证分享卡(换一个有已答问题的测试箱主)" fi say "" say "== 4. 撤销 ==" if [ "$RUN" = 1 ]; then "$TAMABOX" unrestrict --domain "$DOMAIN" restricted=0 check "box page after unrestrict" 200 "$(code "$BASE_URL/_/$DOMAIN")" else say " [dry-run] $TAMABOX unrestrict --domain $DOMAIN" fi say "" say "== 结果: PASS=$pass FAIL=$fail ==" if [ "$fail" -gt 0 ]; then say "有失败项,把上面输出 + 服务日志(journalctl / docker logs 里搜 'Failed to query user restriction')一起发我。" exit 1 fi say "全部通过。仍需人工手测两项:L2(回答应保存为私密)、L3(回答应被拒绝)。"