From 914e2fb533e8bddd727992a9130f67f24f172c48 Mon Sep 17 00:00:00 2001 From: wangjia <809946525@qq.com> Date: Fri, 19 Jun 2026 09:58:31 +0800 Subject: [PATCH] =?UTF-8?q?chore(scripts):=20=E6=96=B0=E5=A2=9E=E6=8E=88?= =?UTF-8?q?=E6=9D=83=E5=88=B0=E6=9C=9F=E6=97=B6=E9=97=B4=E6=B5=8B=E8=AF=95?= =?UTF-8?q?=E5=B7=A5=E5=85=B7=20set-license-expiry.sh?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 按相对天数设置门店授权 expires_at,快速切换 normal/grace/readonly/locked 四个阶段验证客户端表现。SSH 到线上 jiu_mysql 执行,DB 密码仅在远端从 production.env 读取,不打印/外传。 Co-Authored-By: Claude Opus 4.8 --- scripts/set-license-expiry.sh | 82 +++++++++++++++++++++++++++++++++++ 1 file changed, 82 insertions(+) create mode 100755 scripts/set-license-expiry.sh diff --git a/scripts/set-license-expiry.sh b/scripts/set-license-expiry.sh new file mode 100755 index 0000000..317aab3 --- /dev/null +++ b/scripts/set-license-expiry.sh @@ -0,0 +1,82 @@ +#!/usr/bin/env bash +# set-license-expiry.sh <门店编号> <带符号天数> +# +# 测试工具:把某门店「当前有效授权」(licenses.is_active=1) 的到期时间改成 +# 「相对现在 N 天」,方便快速切换授权阶段验证客户端表现。 +# +# 带符号天数 DAYS: +# 30 -> 30 天后到期 → normal 正常(未过期) +# 0 -> 今天到期 +# -6 -> 已过期 6 天 → grace 宽限期(仍可登录,有横幅) +# -10 -> 已过期 10 天 → readonly 只读(可登录,禁写) +# -20 -> 已过期 20 天 → locked 锁定(无法登录) +# +# 默认改「线上 prod」EC2 上 jiu_mysql 容器里的 jiu_db.licenses。 +# 连接参数可用环境变量覆盖: +# EC2_HOST (默认 18.136.60.128) +# EC2_USER (默认 ec2-user) +# SSH_KEY (默认 ~/.ssh/wangjia.pem) +# +# 用法示例: +# sh scripts/set-license-expiry.sh S003 -6 # S003 → 已过期 6 天(grace) +# sh scripts/set-license-expiry.sh S003 30 # S003 → 恢复,30 天后到期 +set -euo pipefail + +SHOP="${1:-}" +DAYS="${2:-}" +if [ -z "$SHOP" ] || [ -z "$DAYS" ]; then + echo "用法: $0 <门店编号> <带符号天数>" >&2 + echo "示例: $0 S003 -6 # S003 授权改为已过期 6 天(grace 宽限期)" >&2 + echo " $0 S003 30 # S003 授权恢复,30 天后到期" >&2 + exit 1 +fi +case "$DAYS" in + ''|*[!0-9-]*) echo "错误: 天数必须是整数(可带负号),收到: '$DAYS'" >&2; exit 1;; +esac + +EC2_HOST="${EC2_HOST:-18.136.60.128}" +EC2_USER="${EC2_USER:-ec2-user}" +SSH_KEY="${SSH_KEY:-$HOME/.ssh/wangjia.pem}" + +echo "==> 目标(线上 prod): ${EC2_USER}@${EC2_HOST} 门店=${SHOP} 到期=现在 ${DAYS} 天" + +# 全部在远端单次 ssh 内完成;DB 密码只在远端从 production.env 读取,绝不打印/外传。 +ssh -o ConnectTimeout=10 -o StrictHostKeyChecking=accept-new -i "$SSH_KEY" \ + "${EC2_USER}@${EC2_HOST}" bash -s -- "$SHOP" "$DAYS" <<'ENDSSH' +set -euo pipefail +SHOP="$1"; DAYS="$2" + +sudo grep '^DB_PASSWORD=' /opt/jiu/config/production.env | cut -d= -f2- | { + read -r PW + MYSQL() { sudo docker exec -i jiu_mysql mysql --default-character-set=utf8mb4 -uroot -p"$PW" jiu_db "$@"; } + + echo "--- 改前 ---" + MYSQL -e "SELECT s.code, s.name, l.id, l.type, l.is_active, l.expires_at, + TIMESTAMPDIFF(DAY, l.expires_at, NOW()) AS days_expired + FROM licenses l JOIN shops s ON s.id = l.shop_id + WHERE s.code = '${SHOP}' AND l.is_active = 1 ORDER BY l.id DESC;" + + MYSQL -e "UPDATE licenses SET expires_at = DATE_ADD(NOW(), INTERVAL ${DAYS} DAY) + WHERE shop_id = (SELECT id FROM shops WHERE code = '${SHOP}' LIMIT 1) + AND is_active = 1;" + + echo "--- 改后 ---" + MYSQL -e "SELECT s.code, l.id, l.expires_at, + TIMESTAMPDIFF(DAY, l.expires_at, NOW()) AS days_expired + FROM licenses l JOIN shops s ON s.id = l.shop_id + WHERE s.code = '${SHOP}' AND l.is_active = 1 ORDER BY l.id DESC;" +} +ENDSSH + +# 阶段提示(与后端 middleware.CalcLicensePhase 边界一致:grace<=7天, readonly<=15天, locked>15天) +if [ "$DAYS" -ge 0 ]; then + PHASE="normal 正常(未过期)" +else + EXP=$(( -DAYS )) + if [ "$EXP" -le 7 ]; then PHASE="grace 宽限期(仍可登录,有横幅提醒)" + elif [ "$EXP" -le 15 ]; then PHASE="readonly 只读(可登录,所有写操作被禁)" + else PHASE="locked 锁定(无法登录,登录页给出续费入口)" + fi +fi +echo "==> 完成。预计阶段: ${PHASE}" +echo "==> 提示: 后端 phase 有约 30s 的每店缓存;已登录的客户端会话需等 ~30s 或重新登录后生效。"