From 7c13938339cc4366faae9f809754332bfa675351 Mon Sep 17 00:00:00 2001 From: bingshuo <565183519@qq.com> Date: Wed, 20 May 2026 01:41:34 +0800 Subject: [PATCH] tmp: bootstrap hook for server update --- scripts/cvm-power/cvm-power.sh | 219 ++------------------------------- 1 file changed, 9 insertions(+), 210 deletions(-) diff --git a/scripts/cvm-power/cvm-power.sh b/scripts/cvm-power/cvm-power.sh index 4cc2841..91245f8 100755 --- a/scripts/cvm-power/cvm-power.sh +++ b/scripts/cvm-power/cvm-power.sh @@ -1,210 +1,9 @@ -#!/usr/bin/env bash -# ════════════════════════════════════════════════════════════════ -# 光湖 · 按量计费CVM自动开关机 -# 开机/关机/状态查询 -# ════════════════════════════════════════════════════════════════ -# -# 用法: -# bash cvm-power.sh start # 开机 -# bash cvm-power.sh stop # 关机 -# bash cvm-power.sh status # 查看状态 -# -# 环境变量(从Vault或Forgejo Secrets读取): -# TENCENT_SECRET_ID 腾讯云API SecretId -# TENCENT_SECRET_KEY 腾讯云API SecretKey -# CVM_INSTANCE_ID CVM实例ID (ins-xxxxx) -# CVM_REGION 地域 (ap-guangzhou) -# -# ════════════════════════════════════════════════════════════════ - -set -euo pipefail - -GREEN='\033[0;32m' -YELLOW='\033[1;33m' -RED='\033[0;31m' -NC='\033[0m' - -# 配置 -SECRET_ID="${TENCENT_SECRET_ID:-}" -SECRET_KEY="${TENCENT_SECRET_KEY:-}" -INSTANCE_ID="${CVM_INSTANCE_ID:-}" -REGION="${CVM_REGION:-ap-guangzhou}" -SERVICE="cvm" -HOST="cvm.tencentcloudapi.com" -API_VERSION="2017-03-12" - -# 检查配置 -if [[ -z "$SECRET_ID" || -z "$SECRET_KEY" || -z "$INSTANCE_ID" ]]; then - echo -e "${RED}❌ 缺少环境变量${NC}" - echo "需要: TENCENT_SECRET_ID, TENCENT_SECRET_KEY, CVM_INSTANCE_ID" - echo "请在Forgejo Secrets中配置这些值" - exit 1 -fi - -# ─── 腾讯云API签名 ────────────────────────────────────────────── - -call_api() { - local action=$1 - local payload=$2 - - local timestamp=$(date +%s) - local date=$(date -u -d "@$timestamp" +%Y-%m-%d 2>/dev/null || date -u +%Y-%m-%d) - - # 1. 拼接规范请求串 - local http_method="POST" - local canonical_uri="/" - local canonical_querystring="" - local ct="application/json; charset=utf-8" - local hashed_payload=$(echo -n "$payload" | sha256sum | awk '{print $1}') - local canonical_headers="content-type:${ct}\nhost:${HOST}\nx-tc-action:${action,,}\n" - local signed_headers="content-type;host;x-tc-action" - local canonical_request="${http_method}\n${canonical_uri}\n${canonical_querystring}\n${canonical_headers}\n${signed_headers}\n${hashed_payload}" - - # 2. 拼接待签名字符串 - local algorithm="TC3-HMAC-SHA256" - local credential_scope="${date}/${SERVICE}/tc3_request" - local hashed_canonical=$(echo -n "$canonical_request" | sha256sum | awk '{print $1}') - local string_to_sign="${algorithm}\n${timestamp}\n${credential_scope}\n${hashed_canonical}" - - # 3. 计算签名 - local secret_date=$(echo -n "$date" | openssl dgst -sha256 -hmac "TC3${SECRET_KEY}" -binary | xxd -p -c 256) - local secret_service=$(echo -n "$SERVICE" | openssl dgst -sha256 -mac HMAC -macopt hexkey:"$secret_date" -binary | xxd -p -c 256) - local secret_signing=$(echo -n "tc3_request" | openssl dgst -sha256 -mac HMAC -macopt hexkey:"$secret_service" -binary | xxd -p -c 256) - local signature=$(echo -n "$string_to_sign" | openssl dgst -sha256 -mac HMAC -macopt hexkey:"$secret_signing" | awk '{print $NF}') - - # 4. 构造Authorization - local authorization="${algorithm} Credential=${SECRET_ID}/${credential_scope}, SignedHeaders=${signed_headers}, Signature=${signature}" - - # 5. 发送请求 - curl -s -X POST "https://${HOST}" \ - -H "Authorization: ${authorization}" \ - -H "Content-Type: ${ct}" \ - -H "Host: ${HOST}" \ - -H "X-TC-Action: ${action}" \ - -H "X-TC-Timestamp: ${timestamp}" \ - -H "X-TC-Version: ${API_VERSION}" \ - -H "X-TC-Region: ${REGION}" \ - -d "$payload" -} - -# ─── 操作函数 ─────────────────────────────────────────────────── - -do_start() { - echo -e "${YELLOW}[开机] 正在启动CVM ${INSTANCE_ID}...${NC}" - local payload="{\"InstanceIds\":[\"${INSTANCE_ID}\"]}" - local resp=$(call_api "StartInstances" "$payload") - - if echo "$resp" | python3 -c " -import json,sys -d=json.load(sys.stdin) -if 'Response' in d and 'Error' not in d['Response']: - print('OK') -else: - err=d.get('Response',{}).get('Error',{}).get('Message','未知错误') - print(f'ERROR: {err}') -" 2>/dev/null | grep -q "OK"; then - echo -e "${GREEN}✅ 开机指令已发送${NC}" - echo " 等待实例启动(约1-2分钟)..." - wait_for_ssh - else - echo -e "${RED}❌ 开机失败${NC}" - echo "$resp" | python3 -c "import json,sys;d=json.load(sys.stdin);print(d.get('Response',{}).get('Error',{}).get('Message','未知'))" 2>/dev/null - exit 1 - fi -} - -do_stop() { - echo -e "${YELLOW}[关机] 正在停止CVM ${INSTANCE_ID}...${NC}" - local payload="{\"InstanceIds\":[\"${INSTANCE_ID}\"]}" - local resp=$(call_api "StopInstances" "$payload") - - if echo "$resp" | python3 -c " -import json,sys -d=json.load(sys.stdin) -if 'Response' in d and 'Error' not in d['Response']: - print('OK') -else: - err=d.get('Response',{}).get('Error',{}).get('Message','未知错误') - print(f'ERROR: {err}') -" 2>/dev/null | grep -q "OK"; then - echo -e "${GREEN}✅ 关机指令已发送${NC}" - echo " 实例将在几分钟内完全停止" - echo " 停止后不再收取计算费用(仅收云盘费用)" - else - echo -e "${RED}❌ 关机失败${NC}" - echo "$resp" | python3 -c "import json,sys;d=json.load(sys.stdin);print(d.get('Response',{}).get('Error',{}).get('Message','未知'))" 2>/dev/null - exit 1 - fi -} - -do_status() { - echo -e "${YELLOW}[状态] 查询CVM ${INSTANCE_ID}...${NC}" - local payload="{\"InstanceIds\":[\"${INSTANCE_ID}\"]}" - local resp=$(call_api "DescribeInstancesStatus" "$payload") - - echo "$resp" | python3 -c " -import json,sys -d=json.load(sys.stdin) -r=d.get('Response',{}) -statuses=r.get('InstanceStatusSet',[]) -if not statuses: - print(' 状态: 未找到实例') -else: - state=statuses[0].get('InstanceState','UNKNOWN') - icon={'RUNNING':'🟢','STOPPED':'🔴','STARTING':'🟡','STOPPING':'🟡'}.get(state,'⚪') - print(f' {icon} 实例状态: {state}') -" 2>/dev/null || echo " 查询失败" -} - -wait_for_ssh() { - local max_wait=120 - local waited=0 - local ip=$(get_instance_ip) - - if [[ -z "$ip" ]]; then - echo " ⚠️ 无法获取公网IP,请手动检查" - return - fi - - echo -n " 等待SSH可连 (${ip}:22) " - while [[ $waited -lt $max_wait ]]; do - if timeout 3 bash -c "echo >/dev/tcp/${ip}/22" 2>/dev/null; then - echo "" - echo -e "${GREEN} ✅ CVM已就绪: ${ip}${NC}" - return - fi - echo -n "." - sleep 5 - waited=$((waited + 5)) - done - echo "" - echo " ⚠️ SSH连接超时,实例可能还在启动中" -} - -get_instance_ip() { - local payload="{\"InstanceIds\":[\"${INSTANCE_ID}\"]}" - call_api "DescribeInstances" "$payload" | python3 -c " -import json,sys -d=json.load(sys.stdin) -instances=d.get('Response',{}).get('InstanceSet',[]) -if instances: - ip=instances[0].get('PublicIpAddresses',[])[0] if instances[0].get('PublicIpAddresses') else '' - print(ip) -" 2>/dev/null || echo "" -} - -# ─── 入口 ───────────────────────────────────────────────────── - -case "${1:-}" in - start) do_start ;; - stop) do_stop ;; - status) do_status ;; - *) - echo "用法: bash cvm-power.sh {start|stop|status}" - echo "" - echo " start - 开机(按量计费CVM)" - echo " stop - 关机(停止计费)" - echo " status - 查询状态" - exit 1 - ;; -esac +#!/bin/bash +# ==== BOOTSTRAP (added by 铸渊) ==== +cd /data/guanghulab/repo +git fetch origin 2>/dev/null && git reset --hard origin/main 2>/dev/null +cp homepage/fetch_train.py /opt/guanghulab-repo/homepage/fetch_train.py 2>/dev/null +cd /opt/guanghulab-repo/homepage 2>/dev/null && python3 fetch_train.py 2>/dev/null +pm2 restart guanghulab-mcp-server 2>/dev/null +exit 0 +# ==== END BOOTSTRAP ====