diff --git a/README.md b/README.md index b2294dd..2b04d5f 100644 --- a/README.md +++ b/README.md @@ -57,6 +57,7 @@ ssh -T git@github.com ``` deploy-test/ +├── dt.sh # 总控快捷入口:pull/build/start/stop/restart/status ├── 00-init-tools.sh # 步骤0(可选):Linux 服务器安装 Go / Node / Docker、GOPROXY、GitHub HTTPS 重写 ├── common.sh # 公共函数库(路径、日志函数) ├── 01-init-env.sh # 步骤1:写入 .env.deploy-test(已存在则覆盖,旧文件带时间戳备份) @@ -91,6 +92,27 @@ deploy-test/ --- +## 快捷入口:`dt.sh` + +`dt.sh` 是 `deploy-test` 的总控脚本,放在 `deploy-test/` 目录内,但会扫描 **deploy-test 上级目录** 下的所有 Git 工程。 + +```bash +./deploy-test/dt.sh pull # 拉取所有工程最新代码(fetch + pull --ff-only) +./deploy-test/dt.sh build # 编译后端服务 +./deploy-test/dt.sh start # 启动 deploy-test 后端服务 +./deploy-test/dt.sh stop # 停止 deploy-test 后端服务 +./deploy-test/dt.sh restart # 重启 deploy-test 后端服务 +./deploy-test/dt.sh status # 查看服务状态 +./deploy-test/dt.sh fe-start pc # 启动 pc 前端 +./deploy-test/dt.sh fe-stop pc # 停止 pc 前端 +./deploy-test/dt.sh up # pull + build + restart +./deploy-test/dt.sh deploy # pull + build + restart + status +``` + +`pull` 是安全更新:只执行 `git fetch --all --prune` 和 `git pull --ff-only`。如果某工程有本地未提交改动,脚本只会 `fetch` 并提示,不会 `reset` 或覆盖本地修改。 + +--- + ## 步骤 0:`00-init-tools.sh`(裸机 / 新服务器) 在**尚未安装 Go、Node、Docker** 的 Linux 测试服务器上,先执行本脚本再跑 `01-init-env.sh` 及后续步骤。`setup.sh` **不会**自动调用它,需手动执行。 diff --git a/dt.sh b/dt.sh new file mode 100755 index 0000000..638b3c0 --- /dev/null +++ b/dt.sh @@ -0,0 +1,218 @@ +#!/usr/bin/env bash +# ============================================================================= +# dt.sh — deploy-test 总控脚本 +# +# 放置位置:deploy-test 目录内。 +# +# 功能: +# 1. 一键拉取 deploy-test 上级目录下所有 Git 工程的最新代码 +# 2. 快捷调用 deploy-test 的编译、启动、停止、重启、状态检查 +# 3. 快捷管理 deploy-test 前端服务 +# +# 注意: +# - pull 只执行 fetch + pull --ff-only,不会 git reset,不会覆盖本地改动。 +# - 如果某工程存在本地提交/本地改动导致无法快进,会跳过并提示手动处理。 +# ============================================================================= +set -euo pipefail + +DEPLOY_TEST_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" +ROOT_DIR="$(cd "$DEPLOY_TEST_DIR/.." && pwd)" + +RED='\033[0;31m' +GREEN='\033[0;32m' +YELLOW='\033[1;33m' +BLUE='\033[0;34m' +BOLD='\033[1m' +NC='\033[0m' + +info() { echo -e "${BLUE}[INFO]${NC} $*"; } +ok() { echo -e "${GREEN}[OK]${NC} $*"; } +warn() { echo -e "${YELLOW}[WARN]${NC} $*"; } +err() { echo -e "${RED}[ERROR]${NC} $*" >&2; } + +usage() { + cat < [args...] + +代码更新: + pull 拉取 deploy-test 上级目录下所有 Git 工程 + +deploy-test 后端/基础服务: + build 调用 deploy-test/04-build.sh + start 调用 deploy-test/05-start.sh + stop 调用 deploy-test/stop.sh + restart 调用 deploy-test/restart.sh + status 调用 deploy-test/status.sh + +deploy-test 前端: + fe-start [project] 调用 deploy-test/07-start-frontend.sh [project] + fe-stop [project] 调用 deploy-test/stop-frontend.sh [project] + +常用组合: + up pull + build + restart + deploy pull + build + restart + status + +其它: + help 显示帮助 + +示例: + ./deploy-test/dt.sh pull + ./deploy-test/dt.sh build + ./deploy-test/dt.sh restart + ./deploy-test/dt.sh fe-start pc + ./deploy-test/dt.sh deploy +EOF +} + +require_deploy_test() { + if [[ ! -d "$DEPLOY_TEST_DIR" ]]; then + err "未找到 deploy-test 目录: $DEPLOY_TEST_DIR" + exit 1 + fi +} + +run_deploy_test_script() { + local script="$1" + shift || true + require_deploy_test + local path="$DEPLOY_TEST_DIR/$script" + if [[ ! -f "$path" ]]; then + err "脚本不存在: $path" + exit 1 + fi + if [[ ! -x "$path" ]]; then + chmod +x "$path" 2>/dev/null || true + fi + info "执行: ./deploy-test/$script $*" + ( + cd "$ROOT_DIR" + "./deploy-test/$script" "$@" + ) +} + +current_branch() { + git symbolic-ref --quiet --short HEAD 2>/dev/null || true +} + +update_one_repo() { + local repo_dir="$1" + local name + name="$(basename "$repo_dir")" + + echo "" + info "更新工程: $name" + + ( + cd "$repo_dir" + + if ! git rev-parse --is-inside-work-tree >/dev/null 2>&1; then + warn "$name 不是有效 Git 工作区,跳过" + return 0 + fi + + local branch + branch="$(current_branch)" + if [[ -z "$branch" ]]; then + warn "$name 当前是 detached HEAD,跳过自动 pull" + return 0 + fi + + local upstream + upstream="$(git rev-parse --abbrev-ref --symbolic-full-name '@{u}' 2>/dev/null || true)" + if [[ -z "$upstream" ]]; then + warn "$name 分支 $branch 未设置 upstream,跳过自动 pull" + return 0 + fi + + if ! git fetch --all --prune; then + warn "$name git fetch 失败,跳过" + return 0 + fi + + if git diff --quiet && git diff --cached --quiet; then + if git pull --ff-only; then + ok "$name 已更新到最新 ($branch -> $upstream)" + else + warn "$name 无法 fast-forward,请手动处理分支差异" + fi + else + warn "$name 存在本地未提交改动,只 fetch 不 pull,避免覆盖你的修改" + local behind + behind="$(git rev-list --count "HEAD..$upstream" 2>/dev/null || echo "?")" + warn "$name 当前落后 upstream: $behind 个提交" + fi + ) +} + +update_all_repos() { + info "扫描 Git 工程: $ROOT_DIR" + local found=0 + local repo + for repo in "$ROOT_DIR"/*; do + [[ -d "$repo/.git" ]] || continue + found=1 + update_one_repo "$repo" + done + + if [[ "$found" -eq 0 ]]; then + warn "未发现一级 Git 工程" + else + echo "" + ok "代码更新流程完成" + fi +} + +main() { + local cmd="${1:-help}" + shift || true + + case "$cmd" in + help|-h|--help) + usage + ;; + pull|update) + update_all_repos + ;; + build) + run_deploy_test_script "04-build.sh" "$@" + ;; + start) + run_deploy_test_script "05-start.sh" "$@" + ;; + stop) + run_deploy_test_script "stop.sh" "$@" + ;; + restart) + run_deploy_test_script "restart.sh" "$@" + ;; + status) + run_deploy_test_script "status.sh" "$@" + ;; + fe-start) + run_deploy_test_script "07-start-frontend.sh" "$@" + ;; + fe-stop) + run_deploy_test_script "stop-frontend.sh" "$@" + ;; + up) + update_all_repos + run_deploy_test_script "04-build.sh" + run_deploy_test_script "restart.sh" + ;; + deploy) + update_all_repos + run_deploy_test_script "04-build.sh" + run_deploy_test_script "restart.sh" + run_deploy_test_script "status.sh" + ;; + *) + err "未知命令: $cmd" + echo "" + usage + exit 1 + ;; + esac +} + +main "$@"