refactor: local.sh 更名为 sites-manage-local.sh,新增 sites-manage-cloud.sh 云端管理脚本

- local.sh → sites-manage-local.sh(重命名,职责更清晰)
- 新增 sites-manage-cloud.sh(云服务器站点启停管理)
- 更新 backup-db.sh、deploy-ai.sh、restore-db.sh
- 添加 .gitignore(忽略 .DS_Store)
This commit is contained in:
aiyimickey 2026-05-18 14:52:40 +08:00
parent 3efb7573ac
commit 78ff4b01b6
7 changed files with 334 additions and 63 deletions

1
.gitignore vendored Normal file
View File

@ -0,0 +1 @@
.DS_Store

111
README.md
View File

@ -1,34 +1,61 @@
# Scripts — 部署与运维脚本
多站点 Docker 项目的运维脚本集合,涵盖本地开发管理、云端部署、数据库备份恢复、内容编辑等
多站点 Docker 项目的运维脚本集合,涵盖本地开发管理、云服务器运维、云端部署、数据库备份恢复。
## 脚本清单
| 脚本 | 用途 | 目标环境 |
|------|------|---------|
| `local.sh` | 本地站点启停管理 | 本地 Docker |
| `sites-manage-local.sh` | 本地站点启停npm run dev + Docker | 本地 |
| `sites-manage-cloud.sh` | 云服务器站点启停SSH / 服务器本地运行) | 云端 |
| `deploy-ai.sh` | 部署站点到 tlyq.aitxjp 服务器) | 云端 |
| `deploy-cc.sh` | 部署站点到 tlyq.cctgz 服务器) | 云端 |
| `edit-site-cc.sh` | www.tlyq.cc 官网内容管理(新闻、联系方式等) | 云端 |
| `backup-db.sh` | 备份 issue-ai 和 assets-ai 数据库 | 云端 → 本地 |
| `restore-db.sh` | 恢复数据库(本地或云端) | 本地 / 云端 |
| `backup-db.sh` | 备份数据库assets / issue / ldap | 云端 → 本地 |
| `restore-db.sh` | 恢复数据库到本地或云端 | 本地 / 云端 |
| `edit-site-cc.sh` | www.tlyq.cc 官网内容管理 | 云端 |
## 详细说明
---
### local.sh — 本地站点管理
## sites-manage-local.sh — 本地站点管理
```bash
bash scripts/local.sh start # 启动所有站点
bash scripts/local.sh stop # 停止所有站点
bash scripts/local.sh restart issue # 重启指定站点
bash scripts/local.sh status # 查看运行状态
bash scripts/sites-manage-local.sh start # 启动全部
bash scripts/sites-manage-local.sh start ai # 启动 ai 全部
bash scripts/sites-manage-local.sh start ldap oa # 启动指定站点
bash scripts/sites-manage-local.sh stop oa # 停止指定站点
bash scripts/sites-manage-local.sh restart ldap # 重启指定站点
bash scripts/sites-manage-local.sh status # 查看状态
```
支持站点:www、cloud、token、issue、assets、ldap、oa。
站点启动方式
启动前自动检查是否有线上域名残留,防止本地开发时跳转到生产环境。
| 站点 | 方式 | 端口 |
|------|------|------|
| ldap | Docker | 6178Web UI、3890LDAP |
| oa | `npm run dev`(宿主机) | 6179 |
| issue | `npm run dev`(宿主机) | 6176 |
| assets | `npm run dev`(宿主机) | 6177 |
| www / cloud / token | Docker | 61736175 |
### deploy-ai.sh — tlyq.ai 部署
## sites-manage-cloud.sh — 云服务器站点管理
```bash
bash scripts/sites-manage-cloud.sh start ai # 启动全部
bash scripts/sites-manage-cloud.sh restart nginx # 重启 nginx
bash scripts/sites-manage-cloud.sh stop oa issue # 停指定站点
bash scripts/sites-manage-cloud.sh status # 查看状态
```
自动检测运行环境:本地 Mac 运行时通过 SSH 操作 txjp在云服务器上运行时直接操作本地 Docker。也可显式指定
```bash
OA_REMOTE=local bash scripts/sites-manage-cloud.sh status # 强制本地模式
OA_REMOTE=ssh bash scripts/sites-manage-cloud.sh status # 强制 SSH 模式
```
站点全部以 Docker 方式运行,依赖关系:`ldap → oa / issue / assets → nginx`。
## deploy-ai.sh — tlyq.ai 部署
```bash
bash scripts/deploy-ai.sh # 自动检测:增量 or 完整构建
@ -36,60 +63,52 @@ bash scripts/deploy-ai.sh --force # 强制完整构建
bash scripts/deploy-ai.sh --restart # 仅重启容器
```
交互式选择站点后执行:源码打包 → 上传 → 服务器构建 → 容器重启。部署 issue/assets 后自动验证 API 连通性(带重试机制)
交互式选择站点17www / cloud / token / issue / assets / oa / ldap
> 详细文档见 [deploy-ai-readme.md](deploy-ai-readme.md)
流程:源码打包 → 上传 → 服务器 `npm install``npm run build` → 容器重建。部署后自动验证。
### deploy-cc.sh — tlyq.cc 部署
LDAP 部署特殊处理:上传 Dockerfile + docker-compose.yml自动创建 .env去除端口映射`--build` 构建含 sqlite3 的镜像。
```bash
bash scripts/deploy-cc.sh
```
交互式选择站点后部署到 tlyq.cctgz 服务器),逻辑与 deploy-ai.sh 类似。
### edit-site-cc.sh — tlyq.cc 官网内容编辑
```bash
bash scripts/edit-site-cc.sh
```
交互式菜单编辑 www.tlyq.cc 的联系方式、新闻动态、时间线等内容,修改后自动部署。
### backup-db.sh — 数据库备份
## backup-db.sh — 数据库备份
```bash
bash scripts/backup-db.sh
```
一键备份 issue-ai 和 assets-ai 的生产数据库:
一键备份三个数据库:
1. 执行 WAL checkpoint 确保数据一致性
2. 在云端 `/root/docker/db-backups/` 保留一份
3. 下载到本地 `~/programs/docker/db-backups/`
4. 验证备份文件为有效 SQLite 数据库
| 数据库 | 服务 | 内容 |
|--------|------|------|
| assets-{时间戳}.db | assets-ai | 设备资产 |
| issue-{时间戳}.db | issue-ai | 工单、配件 |
| ldap-{时间戳}.db | lldap | **全部用户账号** |
### restore-db.sh — 数据库恢复
流程WAL checkpoint → 云端打包 → 云端持久保留 → 下载到本地 → 完整性验证。
> 详细文档见 [BACKUP-RESTORE.md](../docs/BACKUP-RESTORE.md)
## restore-db.sh — 数据库恢复
```bash
# 恢复本地数据库
bash scripts/restore-db.sh local issue issue-20260515_163059.db
# 恢复云端数据库
bash scripts/restore-db.sh cloud assets assets-20260515_163059.db
bash scripts/restore-db.sh cloud issue issue-20260518_1200.db
bash scripts/restore-db.sh cloud ldap ldap-20260518_1200.db
# 恢复本地数据库
bash scripts/restore-db.sh local assets assets-20260518_1200.db
```
恢复流程:停止容器 → 备份当前库 → 替换 → 清理 WAL/SHM → 启动 → 验证。支持 `issue``assets` 两个服务。
支持服务:`assets` / `issue` / `ldap`。流程:检查 → 验证 → 确认 → 备份当前库 → 停止容器 → 替换 → 清理 WAL → 启动 → 验证
## 备份存储路径
| 位置 | 路径 |
|------|------|
| 云端持久备份 | `/root/docker/db-backups/` |
| 本地备份 | `~/programs/docker/db-backups/` |
| 云端临时(传输中) | `/tmp/db-backup/`(完成后清理) |
| 本地备份 | `db-backups/` |
| 云端临时 | `/tmp/db-backup/`(完成后清理) |
## 依赖
- **本地**macOS / Linuxbashssh配置 `txjp``tgz` 别名scpdocker
- **本地**macOS / Linuxbashssh配置 `txjp``tgz` 别名scpdockersqlite3
- **云端**Docker ComposeNode.jsbetter-sqlite3

View File

@ -16,11 +16,14 @@ log "执行 WAL checkpoint (assets)..."
ssh txjp "docker exec assets-ai node -e \"const D=require('better-sqlite3');const db=new D('/app/data/assets.db');db.pragma('wal_checkpoint(TRUNCATE)');db.close();\""
log "执行 WAL checkpoint (issue)..."
ssh txjp "docker exec issue-ai node -e \"const D=require('better-sqlite3');const db=new D('/app/data/issue.db');db.pragma('wal_checkpoint(TRUNCATE)');db.close();\""
log "执行 WAL checkpoint (LLDAP)..."
ssh txjp "docker exec lldap sqlite3 /data/users.db 'PRAGMA wal_checkpoint(TRUNCATE);' 2>/dev/null || true"
# 云端打包
ssh txjp "mkdir -p /tmp/db-backup && \
cp /root/docker/assets-ai/data/assets.db /tmp/db-backup/assets-${TIMESTAMP}.db && \
cp /root/docker/issue-ai/data/issue.db /tmp/db-backup/issue-${TIMESTAMP}.db"
cp /root/docker/issue-ai/data/issue.db /tmp/db-backup/issue-${TIMESTAMP}.db && \
docker cp lldap:/data/users.db /tmp/db-backup/ldap-${TIMESTAMP}.db 2>/dev/null || cp /root/docker/ldap-ai/data/lldap/users.db /tmp/db-backup/ldap-${TIMESTAMP}.db"
# 确保本地备份目录存在
mkdir -p "${LOCAL_DIR}"
@ -29,7 +32,8 @@ mkdir -p "${LOCAL_DIR}"
CLOUD_DIR="/root/docker/db-backups"
ssh txjp "mkdir -p ${CLOUD_DIR} && \
cp /tmp/db-backup/assets-${TIMESTAMP}.db ${CLOUD_DIR}/assets-${TIMESTAMP}.db && \
cp /tmp/db-backup/issue-${TIMESTAMP}.db ${CLOUD_DIR}/issue-${TIMESTAMP}.db"
cp /tmp/db-backup/issue-${TIMESTAMP}.db ${CLOUD_DIR}/issue-${TIMESTAMP}.db && \
cp /tmp/db-backup/ldap-${TIMESTAMP}.db ${CLOUD_DIR}/ldap-${TIMESTAMP}.db"
log "云端备份已保存至: ${CLOUD_DIR}"
# 复制到本地
@ -37,10 +41,11 @@ log "复制到本地..."
mkdir -p "${LOCAL_DIR}"
scp "txjp:/tmp/db-backup/assets-${TIMESTAMP}.db" "${LOCAL_DIR}/"
scp "txjp:/tmp/db-backup/issue-${TIMESTAMP}.db" "${LOCAL_DIR}/"
scp "txjp:/tmp/db-backup/ldap-${TIMESTAMP}.db" "${LOCAL_DIR}/"
# 验证备份文件为有效 SQLite 数据库
log "验证备份完整性..."
for f in "${LOCAL_DIR}/assets-${TIMESTAMP}.db" "${LOCAL_DIR}/issue-${TIMESTAMP}.db"; do
for f in "${LOCAL_DIR}/assets-${TIMESTAMP}.db" "${LOCAL_DIR}/issue-${TIMESTAMP}.db" "${LOCAL_DIR}/ldap-${TIMESTAMP}.db"; do
if ! sqlite3 "$f" "SELECT count(*) FROM sqlite_master" > /dev/null 2>&1; then
echo "[错误] 备份文件无效或损坏: $f"
exit 1
@ -53,6 +58,6 @@ ssh txjp "rm -rf /tmp/db-backup"
log "备份完成:${TIMESTAMP}"
echo " 云端: ${CLOUD_DIR}/"
ssh txjp "ls -lh ${CLOUD_DIR}/assets-${TIMESTAMP}.db ${CLOUD_DIR}/issue-${TIMESTAMP}.db 2>/dev/null"
ssh txjp "ls -lh ${CLOUD_DIR}/assets-${TIMESTAMP}.db ${CLOUD_DIR}/issue-${TIMESTAMP}.db ${CLOUD_DIR}/ldap-${TIMESTAMP}.db 2>/dev/null"
echo " 本地:"
ls -lh "${LOCAL_DIR}"/assets-${TIMESTAMP}.db "${LOCAL_DIR}"/issue-${TIMESTAMP}.db 2>/dev/null
ls -lh "${LOCAL_DIR}"/assets-${TIMESTAMP}.db "${LOCAL_DIR}"/issue-${TIMESTAMP}.db "${LOCAL_DIR}"/ldap-${TIMESTAMP}.db 2>/dev/null

View File

@ -66,8 +66,9 @@ echo " 3) token.tlyq.ai (Token工厂)"
echo " 4) issue.tlyq.ai (工单系统)"
echo " 5) assets.tlyq.ai (资产管理系统)"
echo " 6) oa.tlyq.ai (OA 统一门户 — 含 nginx 配置)"
echo " 7) ldap.tlyq.ai (LLDAP 用户目录服务)"
echo ""
printf "请输入编号 (1/2/3/4/5/6): "
printf "请输入编号 (1/2/3/4/5/6/7): "
read choice
SITE=""; LOCAL_DIR=""; REMOTE_DIR=""; CONTAINER=""
@ -78,6 +79,7 @@ case "$choice" in
4) SITE="issue"; LOCAL_DIR="/Users/niuniu/programs/docker/issue-ai"; REMOTE_DIR="/root/docker/issue-ai"; CONTAINER="issue-ai" ;;
5) SITE="assets"; LOCAL_DIR="/Users/niuniu/programs/docker/assets-ai"; REMOTE_DIR="/root/docker/assets-ai"; CONTAINER="assets-ai" ;;
6) SITE="oa"; LOCAL_DIR="/Users/niuniu/programs/docker/oa-ai"; REMOTE_DIR="/root/docker/oa-ai"; CONTAINER="oa-ai" ;;
7) SITE="ldap"; LOCAL_DIR="/Users/niuniu/programs/docker/ldap-ai"; REMOTE_DIR="/root/docker/ldap-ai"; CONTAINER="lldap" ;;
*) echo "无效选择"; exit 1 ;;
esac
@ -419,6 +421,23 @@ CHECKEOF
info "部署 nginx 配置..."
ssh txjp "cp $REMOTE_DIR/../nginx-proxy-ai/conf.d/oa-ai.conf /root/docker/nginx-proxy-ai/conf.d/ 2>/dev/null || true
docker exec nginx-ai nginx -t && docker exec nginx-ai nginx -s reload" ;;
ldap)
info "部署 LLDAP..."
scp "$LOCAL_DIR/docker-compose.yml" txjp:$REMOTE_DIR/docker-compose.yml
scp "$LOCAL_DIR/Dockerfile" txjp:$REMOTE_DIR/Dockerfile
ssh txjp "cd $REMOTE_DIR && \
if [ ! -f .env ]; then \
echo 'LLDAP_JWT_SECRET='\$(docker exec lldap printenv LLDAP_JWT_SECRET 2>/dev/null) > .env && \
echo 'LLDAP_LDAP_USER_PASS='\$(docker exec lldap printenv LLDAP_LDAP_USER_PASS 2>/dev/null) >> .env && \
echo 'LLDAP_LDAP_BASE_DN=dc=tlyq,dc=ai' >> .env && \
echo 'LLDAP_HTTP_PORT=17170' >> .env && \
echo 'LLDAP_LDAP_PORT=3890' >> .env && \
echo 'LLDAP_DATABASE_PATH=/data/users.db' >> .env && \
echo 'LLDAP_ADMIN_PASSWORD='\$(docker exec lldap printenv LLDAP_ADMIN_PASSWORD 2>/dev/null) >> .env && \
fi && \
sed -i '/3890:3890/d' docker-compose.yml 2>/dev/null || true && \
docker compose up -d --build && docker compose restart"
log "LLDAP 已部署" ;;
esac
# ============================================================
@ -437,9 +456,14 @@ case "$SITE" in
issue) URL="https://issue.tlyq.ai" ;;
assets) URL="https://assets.tlyq.ai" ;;
oa) URL="https://oa.tlyq.ai" ;;
ldap) URL="http://localhost:6178" ;;
esac
STATUS=$(ssh txjp "curl -s -o /dev/null -w '%{http_code}' -k '$URL' 2>/dev/null" 2>/dev/null || echo "???")
if [[ "$SITE" == "ldap" ]]; then
STATUS=$(ssh txjp "docker exec lldap wget -q -O - http://127.0.0.1:17170 > /dev/null 2>&1 && echo 200 || echo 000" 2>/dev/null || echo "???")
else
STATUS=$(ssh txjp "curl -s -o /dev/null -w '%{http_code}' -k '$URL' 2>/dev/null" 2>/dev/null || echo "???")
fi
if [[ "$STATUS" == "200" || "$STATUS" == "307" || "$STATUS" == "301" ]]; then
log "部署成功!总耗时: ${TOTAL_DUR}s | 访问 $URL"
exit 0

View File

@ -6,21 +6,23 @@
# 恢复本地数据库: bash scripts/restore-db.sh local <服务名> <备份文件名>
# 恢复云端数据库: bash scripts/restore-db.sh cloud <服务名> <备份文件名>
#
# 服务名: issue / assets
# 服务名: issue / assets / ldap
#
# 示例:
# bash scripts/restore-db.sh local issue issue-2026-04-29_1753.db
# bash scripts/restore-db.sh cloud assets assets-2026-04-29_1753.db
# bash scripts/restore-db.sh cloud ldap ldap-2026-05-15_1200.db
# ============================================
set -e
# ---- 参数检查 ----
if [ $# -lt 3 ]; then
echo "用法: $0 <local|cloud> <issue|assets> <备份文件名>"
echo "用法: $0 <local|cloud> <issue|assets|ldap> <备份文件名>"
echo ""
echo "示例:"
echo " $0 local issue issue-2026-04-29_1753.db"
echo " $0 cloud ldap ldap-2026-05-15_1200.db"
echo " $0 cloud assets assets-2026-04-29_1753.db"
echo ""
echo "可用备份文件:"
@ -52,8 +54,14 @@ case $SERVICE in
DB_PATH_IN_CONTAINER="/app/data/assets.db"
LOCAL_DB_PATH="/Users/niuniu/programs/docker/assets-ai/data/assets.db"
;;
ldap)
PROJECT_DIR="ldap-ai"
CONTAINER="lldap"
DB_PATH_IN_CONTAINER="/data/users.db"
LOCAL_DB_PATH="/Users/niuniu/programs/docker/ldap-ai/data/lldap/users.db"
;;
*)
echo "错误: 服务名必须是 issue 或 assets"
echo "错误: 服务名必须是 issue、assets 或 ldap"
exit 1
;;
esac

214
sites-manage-cloud.sh Normal file
View File

@ -0,0 +1,214 @@
#!/bin/bash
# 站点管理脚本(自动适配本地/云端)
#
# 本地 Mac 运行 → 通过 SSH 操作 txjp 服务器
# 云服务器运行 → 直接操作本地 Docker
#
# 用法bash sites-manage-cloud.sh <命令> [站点名...]
# 站点名ldap www cloud token gitea issue assets oa nginx
# ai上述全部、all同 ai
set -e
# ============================================================
# 自动检测运行环境
#
# 优先级:
# 1. OA_REMOTE 环境变量 — "local" 强制本地 / "ssh" 强制远程
# 2. hostname 匹配 — 包含 "Tencent" 则判为云服务器本地
# 3. 以上都不满足 → SSH 远程模式
# ============================================================
THIS_HOST=$(hostname 2>/dev/null || uname -n 2>/dev/null || echo "")
if [ "$OA_REMOTE" = "local" ]; then
IS_LOCAL_SERVER=true
LABEL="txjp本地运行 · 手动指定)"
elif [ "$OA_REMOTE" = "ssh" ]; then
IS_LOCAL_SERVER=false
SERVER="txjp"
LABEL="txjpSSH 远程 · 手动指定)"
elif echo "$THIS_HOST" | grep -qi "Tencent"; then
IS_LOCAL_SERVER=true
LABEL="txjp本地运行 · 自动检测)"
else
IS_LOCAL_SERVER=false
SERVER="txjp"
LABEL="txjpSSH 远程 · 自动检测)"
fi
# 执行命令:服务器本地直接跑,否则 SSH
run() {
if $IS_LOCAL_SERVER; then
bash -c "$*"
else
ssh $SERVER "$*"
fi
}
BASE="/root/docker"
# 站点 → 目录 & 容器名
declare -A SITE_DIR
SITE_DIR[ldap]="ldap-ai"
SITE_DIR[www]="www-ai"
SITE_DIR[cloud]="cloud-ai"
SITE_DIR[token]="token-ai"
SITE_DIR[gitea]="gitea-ai"
SITE_DIR[issue]="issue-ai"
SITE_DIR[assets]="assets-ai"
SITE_DIR[oa]="oa-ai"
SITE_DIR[nginx]="nginx-proxy-ai"
SITE_DIR[sso]="sso-ai"
declare -A SITE_CONTAINER
SITE_CONTAINER[ldap]="lldap"
SITE_CONTAINER[www]="www-ai"
SITE_CONTAINER[cloud]="cloud-ai"
SITE_CONTAINER[token]="token-ai"
SITE_CONTAINER[gitea]="gitea-ai"
SITE_CONTAINER[issue]="issue-ai"
SITE_CONTAINER[assets]="assets-ai"
SITE_CONTAINER[oa]="oa-ai"
SITE_CONTAINER[nginx]="nginx-ai"
SITE_CONTAINER[sso]="sso-ai"
AI_SITES="ldap www cloud token gitea issue assets oa nginx"
GREEN='\033[0;32m'; YELLOW='\033[1;33m'; CYAN='\033[0;36m'; RED='\033[0;31m'; NC='\033[0m'
log() { printf "${GREEN}[✓]${NC} %s\n" "$1"; }
warn() { printf "${YELLOW}[!]${NC} %s\n" "$1"; }
err() { printf "${RED}[✗]${NC} %s\n" "$1"; }
expand_sites() {
local result=()
for s in "$@"; do
case $s in
ai|all) for x in $AI_SITES; do result+=("$x"); done ;;
*) result+=("$s") ;;
esac
done
echo "${result[@]}"
}
# ============================================================
# 操作
# ============================================================
remote_start() {
local name=$1 dir="${BASE}/${SITE_DIR[$name]}"
local container="${SITE_CONTAINER[$name]}"
if run "docker ps --format '{{.Names}}' | grep -q '^${container}$'" 2>/dev/null; then
warn "$name 已在运行"
return
fi
log "启动 $name ..."
run "cd $dir && docker compose up -d" 2>/dev/null && log "$name 已启动" || err "$name 启动失败"
}
remote_stop() {
local name=$1 dir="${BASE}/${SITE_DIR[$name]}"
local container="${SITE_CONTAINER[$name]}"
if ! run "docker ps --format '{{.Names}}' | grep -q '^${container}$'" 2>/dev/null; then
warn "$name 未在运行"
return
fi
log "停止 $name ..."
run "cd $dir && docker compose down" 2>/dev/null && log "$name 已停止" || err "$name 停止失败"
}
remote_status() {
local targets=("$@")
echo ""
printf "${CYAN}=========================================${NC}\n"
printf "${CYAN} 站点状态 — ${LABEL}${NC}\n"
printf "${CYAN}=========================================${NC}\n"
echo ""
for name in "${targets[@]}"; do
local container="${SITE_CONTAINER[$name]}"
local status
status=$(run "docker ps --format '{{.Status}}' -f name=^${container}$" 2>/dev/null || echo "")
if [ -n "$status" ]; then
printf " ${GREEN}${NC} %-8s 运行中 (%s)\n" "$name" "$status"
else
printf " ${RED}${NC} %-8s 未运行\n" "$name"
fi
done
echo ""
}
show_help() {
echo ""
printf "${CYAN}用法:${NC} bash sites-manage-cloud.sh <命令> [站点名...]\n"
echo ""
echo " 当前环境: ${LABEL}"
echo ""
echo " 命令:"
echo " start 启动站点"
echo " stop 停止站点"
echo " restart 重启站点"
echo " status 查看状态"
echo ""
echo " 站点名(可指定多个,空格分隔):"
echo " ldap LLDAP 用户目录"
echo " www tlyq.ai 官网"
echo " cloud 云平台登录页"
echo " token Token 工厂登录页"
echo " gitea Gitea 代码托管"
echo " issue 工单系统"
echo " assets 设备资产管理"
echo " oa OA 统一门户"
echo " nginx 反向代理"
echo " ai 全部 tlyq.ai 站点"
echo ""
echo "示例:"
echo " bash sites-manage-cloud.sh start ai # 启动全部"
echo " bash sites-manage-cloud.sh restart nginx # 重启 nginx"
echo " bash sites-manage-cloud.sh stop oa issue # 停 OA + 工单"
echo " bash sites-manage-cloud.sh status # 查看所有状态"
echo ""
}
# ============================================================
# 入口
# ============================================================
ACTION=${1:-}
shift || true
if [ -z "$ACTION" ]; then
show_help
exit 0
fi
mapfile -t TARGETS < <(expand_sites "$@")
if [ ${#TARGETS[@]} -eq 0 ]; then
mapfile -t TARGETS < <(expand_sites ai)
fi
case $ACTION in
start)
for s in "${TARGETS[@]}"; do remote_start "$s"; done
;;
stop)
for s in "${TARGETS[@]}"; do remote_stop "$s"; done
;;
restart)
for s in "${TARGETS[@]}"; do remote_stop "$s"; done
echo ""
log "等待 2 秒后启动..."
sleep 2
for s in "${TARGETS[@]}"; do remote_start "$s"; done
;;
status)
remote_status "${TARGETS[@]}"
;;
help|--help|-h)
show_help
;;
*)
err "未知命令: $ACTION"
show_help
exit 1
;;
esac

View File

@ -1,6 +1,6 @@
#!/bin/bash
# 本地站点管理:启动 / 停止 / 重启 / 状态
# 用法bash local.sh [start|stop|restart|status] [站点名...]
# 用法bash sites-manage-local.sh [start|stop|restart|status] [站点名...]
# 不加参数则交互选择
#
# 站点名:
@ -237,7 +237,7 @@ show_status() {
# ============================================================
show_help() {
echo ""
printf "${CYAN}用法:${NC} bash local.sh <命令> [站点名...]\n"
printf "${CYAN}用法:${NC} bash sites-manage-local.sh <命令> [站点名...]\n"
echo ""
echo " 命令:"
echo " start 启动站点"
@ -253,11 +253,11 @@ show_help() {
echo " all — 全部站点"
echo ""
echo "示例:"
echo " bash local.sh start all # 启动全部"
echo " bash local.sh start ai # 启动 ai 全部"
echo " bash local.sh start issue assets # 只启 issue + assets"
echo " bash local.sh stop www-ai # 只停 www-ai"
echo " bash local.sh status # 查看所有状态"
echo " bash sites-manage-local.sh start all # 启动全部"
echo " bash sites-manage-local.sh start ai # 启动 ai 全部"
echo " bash sites-manage-local.sh start issue assets # 只启 issue + assets"
echo " bash sites-manage-local.sh stop www-ai # 只停 www-ai"
echo " bash sites-manage-local.sh status # 查看所有状态"
echo ""
}