{"id":51348011,"url":"https://github.com/showx/jenshow","last_synced_at":"2026-07-02T13:06:20.185Z","repository":{"id":363715418,"uuid":"1263838496","full_name":"showx/jenshow","owner":"showx","description":"jenshow ci/cd","archived":false,"fork":false,"pushed_at":"2026-06-10T03:50:03.000Z","size":18,"stargazers_count":1,"open_issues_count":0,"forks_count":0,"subscribers_count":0,"default_branch":"master","last_synced_at":"2026-06-10T05:06:09.403Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"Shell","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/showx.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2026-06-09T10:06:50.000Z","updated_at":"2026-06-10T03:50:07.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/showx/jenshow","commit_stats":null,"previous_names":["showx/jenshow"],"tags_count":null,"template":false,"template_full_name":null,"purl":"pkg:github/showx/jenshow","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/showx%2Fjenshow","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/showx%2Fjenshow/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/showx%2Fjenshow/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/showx%2Fjenshow/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/showx","download_url":"https://codeload.github.com/showx/jenshow/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/showx%2Fjenshow/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":35048165,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-26T15:22:16.424Z","status":"online","status_checked_at":"2026-07-02T02:00:06.368Z","response_time":173,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2026-07-02T13:06:19.226Z","updated_at":"2026-07-02T13:06:20.173Z","avatar_url":"https://github.com/showx.png","language":"Shell","funding_links":[],"categories":[],"sub_categories":[],"readme":"# jenshow 部署脚本\n\n一套用于 Linux 服务器的**环境搭建**与**前后端发布**脚本，支持 `curl` 一键安装。\n\n- 代码仓库：[github.com/showx/jenshow](https://github.com/showx/jenshow)\n- 脚本源：`https://raw.githubusercontent.com/showx/jenshow/master`\n\n---\n\n## 快速开始\n\n### 1. 交互式配置（推荐，curl 一步步来）\n\n**本机：交互配置 + 下载发布脚本**\n\n```bash\ncurl -fsSL https://raw.githubusercontent.com/showx/jenshow/master/install.sh | bash -s -- init ./myproject\n```\n\n会依次询问（回车即用默认值）：\n\n1. **项目标识** — 项目名、API 域名、服务器 IP、SSH 用户  \n2. **运行参数** — 前端路由、后端端口  \n3. **目录布局**（可选高级）— Go/前端源码路径  \n\n确认后生成 `project.conf` 并下载全部脚本；完成后可选择在远程服务器自动搭建环境（Nginx + Supervisor + Redis）。\n\n**仅交互生成配置（不下载脚本）：**\n\n```bash\ncurl -fsSL https://raw.githubusercontent.com/showx/jenshow/master/install.sh | bash -s -- configure\n```\n\n**服务器：交互配置 + 环境搭建（需 root）：**\n\n```bash\ncurl -fsSL https://raw.githubusercontent.com/showx/jenshow/master/install.sh | sudo bash -s -- setup-init\n```\n\n\u003e 说明：curl 管道执行时仍可在终端输入，脚本从 `/dev/tty` 读取。若无 TTY，请先下载再执行：  \n\u003e `curl -fsSL ... -o install.sh \u0026\u0026 bash install.sh init`\n\n### 2. 非交互方式（已有配置或环境变量）\n\n```bash\nPROJECT_NAME=qsdk API_DOMAIN=qsdk.example.com \\\ncurl -fsSL https://raw.githubusercontent.com/showx/jenshow/master/install.sh | sudo bash -s -- setup\n```\n\n本地已有 `project.conf` 时：`sudo ./setup_server.sh`\n\n### 3. 本机仅下载脚本（无交互，使用模板）\n\n```bash\ncurl -fsSL https://raw.githubusercontent.com/showx/jenshow/master/install.sh | bash -s -- deploy-scripts ./my-project\n```\n\n### 4. 发布后端\n\n在 `BACKEND_DIR` 对应目录下（默认 `backend/`）：\n\n```bash\n# 编译 + 上传 + 远程部署（推荐）\n./publish.sh\n./publish.sh 20260109_1530\n\n# 等价快捷方式\n./build_upload_deploy.sh\n\n# 仅编译 + 上传\n./publish.sh --upload-only\n./build_and_upload.sh\n```\n\n### 5. 发布前端\n\n在 `FRONTEND_DIR` 对应目录下（默认 `frontend/`）：\n\n```bash\n./build_and_upload.sh\n\n# 指定版本号\n./build_and_upload.sh 20260109_1530\n```\n\n---\n\n## 目录结构\n\n```\njenshow/\n├── project.conf.example      # 配置模板（提交到仓库）\n├── project.conf              # 各项目实际配置（本地/业务仓库，勿提交 jenshow）\n├── project_lib.sh            # 配置加载与 Supervisor 模板生成\n├── install.sh                # curl 安装入口\n├── setup_server.sh           # 完整服务器环境搭建\n├── setup_server_common.sh    # 仅基础软件安装\n├── setup_lib.sh              # setup 幂等工具库\n├── backend/\n│   ├── publish.sh              # 后端发布主脚本\n│   ├── build_and_upload.sh     # → publish.sh --upload-only\n│   ├── build_upload_deploy.sh  # → publish.sh\n│   └── deploy.sh               # 服务器端切换版本\n└── frontend/\n    └── build_and_upload.sh   # 构建 + 打包 + 上传 + 解压部署\n```\n\n---\n\n## 两个层次，别混用\n\n| 层次 | 是什么 | 要不要推送到 jenshow |\n|------|--------|----------------------|\n| **工具仓库** | [showx/jenshow](https://github.com/showx/jenshow) — 脚本、模板 | 直接推送，`project.conf.example` 即可 |\n| **项目配置** | 每个业务项目一份 `project.conf` | **不要**推进工具仓库 |\n\n工具仓库里只有 `project.conf.example`（占位符）。每个项目在使用时复制并修改：\n\n```bash\ncp project.conf.example project.conf\n# 编辑 PROJECT_NAME、SERVER_HOST、API_DOMAIN …\n```\n\n`project.conf` 已加入 `.gitignore`，避免误提交某个项目的 IP/域名。\n\n---\n\n## 核心概念：配置驱动\n\n所有路径由 **`project.conf`** 统一管理，分为三类：\n\n1. **项目标识** — `PROJECT_NAME` 决定服务名、服务器 `WEB_ROOT`\n2. **本地目录** — 脚本位置、源码位置、构建产物（相对 `project.conf` 所在目录）\n3. **服务器目录** — 上传到服务器的目标路径（相对 `/webwww/www/${PROJECT_NAME}`）\n\n### 服务器侧（由 PROJECT_NAME 推导）\n\n以 `PROJECT_NAME=\"myapp\"` 为例：\n\n| 项目 | 默认值 |\n|------|--------|\n| 部署根目录 | `/webwww/www/myapp/` |\n| 后端部署目录 | `/webwww/www/myapp/backend/` |\n| 前端静态目录 | `/webwww/www/myapp/frontend/dist/` |\n| Supervisor 程序名 | `myapp-server` |\n| Nginx 站点配置 | `/etc/nginx/sites-enabled/myapp.conf` |\n\n### 目录配置\n\n本地与服务器使用相同目录名（相对 `project.conf` / `WEB_ROOT`）：\n\n```bash\nBACKEND_DIR=\"backend\"             # 后端：脚本 + Go 源码 + 服务器部署\nFRONTEND_DIR=\"frontend\"           # 前端：脚本 + 源码 + 服务器部署\nFRONTEND_DIST=\"dist\"              # 前端构建产物子目录\nGO_BUILD_TARGET=\".\"               # go build 目标\nFRONTEND_BUILD_CMD=\"npm run build\"\n```\n\n### 目录布局示例\n\n```\nmyrepo/\n├── project.conf\n├── backend/          ← BACKEND_DIR（脚本 + Go 代码）\n└── frontend/         ← FRONTEND_DIR（脚本 + 前端代码）\n```\n\n发布脚本会从自身位置**向上查找** `project.conf`，因此脚本目录可以任意嵌套。\n\n### 基础配置\n\n```bash\nPROJECT_NAME=\"myapp\"\nSERVER_USER=\"root\"\nSERVER_HOST=\"1.2.3.4\"             # 发布时必填\nAPI_DOMAIN=\"api.example.com\"\nFRONTEND_ROUTE=\"/adminxend\"\nBACKEND_PORT=\"8080\"\n```\n\n---\n\n## 部署流程说明\n\n### 后端\n\n```\n本机 build_upload_deploy.sh\n  ├─ go build（按 BACKEND_DIR / GO_BUILD_TARGET 编译）\n  ├─ 输出 myapp-server\u003c版本号\u003e 到 backend/ 脚本目录\n  ├─ scp 上传到服务器 backend/\n  └─ ssh 远程执行 deploy.sh \u003c版本号\u003e\n       ├─ chmod 744\n       ├─ ln -snf 更新软链 myapp-server\n       └─ supervisorctl restart myapp-server\n```\n\n### 前端\n\n```\n本机 build_and_upload.sh\n  ├─ npm run build\n  ├─ tar 打包 dist\n  ├─ scp 上传到服务器 frontend/\n  └─ ssh 远程解压\n       ├─ dist → dist_old（备份）\n       └─ 解压新版本到 dist/\n```\n\n### 服务器 setup 做了什么\n\n`setup_server.sh` 会依次完成：\n\n1. 更新 apt 软件源（已安装时可跳过 upgrade）\n2. 安装 Nginx、Supervisor、Redis\n3. 配置 SSH（关闭密码登录、支持 ssh-rsa 密钥）\n4. 创建项目目录并设置权限\n5. 写入 Nginx 站点配置\n6. 写入 Supervisor 配置（按 `PROJECT_NAME` 命名）\n7. 同步 `project.conf` 和 `deploy.sh` 到服务器 `backend/` 目录\n\n---\n\n## 幂等设计（可重复执行）\n\n所有 setup 脚本支持**重复运行**，已完成的步骤会自动跳过，输出 `⏭ 跳过:` 提示：\n\n| 检测项 | 行为 |\n|--------|------|\n| apt 软件包 | 已安装则跳过 |\n| apt upgrade | 核心软件均已安装则跳过 |\n| systemd 服务 | 已在运行则跳过 |\n| SSH 配置 | 已是目标配置则跳过，不重复覆盖 `.bak` |\n| 目录 | 已存在则跳过创建 |\n| Nginx / Supervisor 配置 | 内容无变化则跳过重载 |\n| deploy.sh | 已存在则跳过下载 |\n\n### 强制覆盖选项\n\n```bash\n# 强制系统升级\nsudo FORCE_UPGRADE=1 ./setup_server.sh\n\n# 强制重新下载 deploy.sh\nsudo FORCE=1 ./setup_server.sh\n```\n\n---\n\n## 环境变量\n\nsetup 时可通过环境变量覆盖 `project.conf`（适合 curl 一行命令）：\n\n```bash\nPROJECT_NAME=myapp \\\nAPI_DOMAIN=api.example.com \\\ncurl -fsSL https://raw.githubusercontent.com/showx/jenshow/master/install.sh | sudo bash -s -- setup\n```\n\n| 变量 | 说明 |\n|------|------|\n| `JENSHOW_BASE_URL` | 脚本下载源（GitHub raw 地址） |\n| `PROJECT_NAME` | 项目名 |\n| `API_DOMAIN` | Nginx server_name |\n| `FRONTEND_ROUTE` | 前端 SPA 路由前缀 |\n| `BACKEND_PORT` | 后端监听端口 |\n| `FORCE_UPGRADE` | `1` = 强制 apt upgrade |\n| `FORCE` | `1` = 强制覆盖 deploy.sh |\n\n---\n\n## 服务器目录布局\n\n以 `PROJECT_NAME=myapp` 为例，setup 完成后服务器上的目录：\n\n```\n/webwww/www/myapp/\n├── backend/\n│   ├── project.conf              # setup 自动同步\n│   ├── deploy.sh                 # setup 自动下载\n│   ├── myapp-server              # 软链 → 当前版本二进制\n│   └── myapp-server20260109_1530 # 实际上线的二进制\n└── frontend/\n    ├── dist/                     # 当前前端静态文件\n    ├── dist_old/                 # 上一次部署备份\n    └── dist_20260109_1530.tar.gz # 上传的压缩包\n```\n\n---\n\n## 前置要求\n\n### 服务器\n\n- Ubuntu / Debian 系 Linux\n- root 权限\n- 可访问 apt 源\n\n### 本机（发布时）\n\n- **后端**：Go 工具链、SSH 免密登录到服务器\n- **前端**：Node.js、npm、SSH 免密登录到服务器\n\n---\n\n## 常见问题\n\n**Q: 之前用的是 `qsdk2` 目录，怎么兼容？**\n\n在 `project.conf` 中设置 `PROJECT_NAME=\"qsdk2\"`，路径会变为 `/webwww/www/qsdk2/`，服务名为 `qsdk2-server`。\n\n**Q: curl setup 时找不到 project.conf？**\n\n正常。setup 不会从工具仓库拉某个项目的配置。请传 `PROJECT_NAME` 等环境变量，或在执行目录放好该项目的 `project.conf`。\n\n**Q: Supervisor 启动失败？**\n\n首次 setup 时后端二进制尚未上传，`myapp-server` 不存在导致启动失败是正常现象。执行 `build_upload_deploy.sh` 发布后端后即可。\n\n**Q: 如何查看服务状态？**\n\n```bash\nsupervisorctl status myapp-server    # 替换为你的 PROJECT_NAME-server\ntail -f /var/log/myapp-server.out.log\n```\n\n---\n\n## 脚本速查\n\n| 脚本 | 运行位置 | 作用 |\n|------|----------|------|\n| `install.sh configure` | 本机/服务器 | 交互式生成 project.conf |\n| `install.sh init` | 本机 | 交互配置 + 下载脚本 |\n| `install.sh setup-init` | 服务器 | 交互配置 + 环境搭建 |\n| `install.sh setup` | 服务器 | curl 完整环境搭建 |\n| `install.sh setup-common` | 服务器 | curl 基础软件安装 |\n| `install.sh deploy-scripts` | 本机 | curl 下载全部发布脚本 |\n| `setup_server.sh` | 服务器 | 完整环境搭建 |\n| `setup_server_common.sh` | 服务器 | 基础软件安装 |\n| `backend/publish.sh` | 本机 | 后端发布主脚本 |\n| `backend/build_upload_deploy.sh` | 本机 | 后端一键发布（调用 publish.sh） |\n| `backend/build_and_upload.sh` | 本机 | 仅编译上传 |\n| `backend/deploy.sh` | 服务器 | 切换后端版本 |\n| `frontend/build_and_upload.sh` | 本机 | 前端一键发布 |\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fshowx%2Fjenshow","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fshowx%2Fjenshow","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fshowx%2Fjenshow/lists"}