feat: 发布包目录架构重构为标准scert根目录与deploy部署运维套件标准化
Some checks are pending
Some checks are pending
This commit is contained in:
parent
2453e5fa1f
commit
ab9da570ec
170
deploy/install-systemd.sh
Normal file
170
deploy/install-systemd.sh
Normal file
@ -0,0 +1,170 @@
|
||||
#!/usr/bin/env bash
|
||||
set -euo pipefail
|
||||
|
||||
# Scert 生产环境全新一键安装部署脚本 (755)
|
||||
|
||||
usage() {
|
||||
echo "用法:$0 [安装根目录]"
|
||||
echo "全新部署会初始化 Scert 专属运行目录并配置 systemd 系统服务。"
|
||||
}
|
||||
|
||||
if [ "${1:-}" = "-h" ] || [ "${1:-}" = "--help" ]; then
|
||||
usage
|
||||
exit 0
|
||||
fi
|
||||
|
||||
if [ "$(id -u)" -ne 0 ]; then
|
||||
echo "错误:必须使用 root 用户执行全新安装!" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
script_dir="$(cd "$(dirname "$0")" && pwd)"
|
||||
package_root="$(realpath -e -- "$script_dir/..")"
|
||||
|
||||
runtime_dir="${1:-/scert}"
|
||||
fresh_confirmation="确认全新部署 Scert"
|
||||
|
||||
printf '这是不可逆的 Scert 专属数据与环境部署操作。请输入“%s”继续: ' "$fresh_confirmation"
|
||||
if ! IFS= read -r confirmation || [ "$confirmation" != "$fresh_confirmation" ]; then
|
||||
echo "未获得有效确认,已取消全新部署。" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
case "$(uname -m)" in
|
||||
x86_64) arch=amd64 ;;
|
||||
aarch64|arm64) arch=arm64 ;;
|
||||
*) echo "错误:不支持的系统架构 $(uname -m)" >&2; exit 1 ;;
|
||||
esac
|
||||
|
||||
# 1. 查找二进制程序
|
||||
if [ -f "$package_root/scert" ] && [ -f "$package_root/scert-admin" ]; then
|
||||
src_scert="$package_root/scert"
|
||||
src_scert_admin="$package_root/scert-admin"
|
||||
src_scert_nginx="$package_root/scert-nginx"
|
||||
src_scert_storage="$package_root/scert-storage"
|
||||
else
|
||||
echo "错误:未能在 $package_root 目录下找到必要的 scert/scert-admin 二进制!" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# 2. 停止旧服务
|
||||
echo ">>> 正在检查并停止已有相关服务..."
|
||||
systemctl stop Scert.service 2>/dev/null || true
|
||||
systemctl stop Scert-admin.service 2>/dev/null || true
|
||||
systemctl stop scert-nginx.service 2>/dev/null || true
|
||||
systemctl stop Scert-storage.service 2>/dev/null || true
|
||||
|
||||
# 3. 创建系统专用运行用户与组
|
||||
if ! getent group Scert >/dev/null; then
|
||||
groupadd --system Scert
|
||||
fi
|
||||
if ! getent passwd Scert >/dev/null; then
|
||||
useradd --system --gid Scert --home-dir "$runtime_dir" --shell /usr/sbin/nologin Scert
|
||||
fi
|
||||
|
||||
# 4. 创建标准目录结构
|
||||
echo ">>> 正在创建标准目录结构: $runtime_dir"
|
||||
mkdir -p "$runtime_dir"
|
||||
for dir in config data log ssl web conf deploy; do
|
||||
mkdir -p "$runtime_dir/$dir"
|
||||
done
|
||||
|
||||
# 5. 安装二进制文件
|
||||
echo ">>> 正在安装程序文件..."
|
||||
cp -f "$src_scert" "$runtime_dir/scert"
|
||||
chown Scert:Scert "$runtime_dir/scert"
|
||||
chmod 0755 "$runtime_dir/scert"
|
||||
|
||||
cp -f "$src_scert_admin" "$runtime_dir/scert-admin"
|
||||
chown root:root "$runtime_dir/scert-admin"
|
||||
chmod 0700 "$runtime_dir/scert-admin"
|
||||
|
||||
if [ -f "$src_scert_nginx" ]; then
|
||||
cp -f "$src_scert_nginx" "$runtime_dir/scert-nginx"
|
||||
chown root:root "$runtime_dir/scert-nginx"
|
||||
chmod 0755 "$runtime_dir/scert-nginx"
|
||||
fi
|
||||
|
||||
if [ -f "$src_scert_storage" ]; then
|
||||
cp -f "$src_scert_storage" "$runtime_dir/scert-storage"
|
||||
chown root:root "$runtime_dir/scert-storage"
|
||||
chmod 0755 "$runtime_dir/scert-storage"
|
||||
fi
|
||||
|
||||
# 6. 复制前端静态文件与部署套件
|
||||
if [ -d "$package_root/web" ]; then
|
||||
cp -rf "$package_root/web"/* "$runtime_dir/web/" 2>/dev/null || true
|
||||
fi
|
||||
if [ -d "$package_root/deploy" ]; then
|
||||
cp -rf "$package_root/deploy"/* "$runtime_dir/deploy/" 2>/dev/null || true
|
||||
chmod -R 0755 "$runtime_dir/deploy" 2>/dev/null || true
|
||||
fi
|
||||
|
||||
chown -R Scert:Scert "$runtime_dir/config" "$runtime_dir/data" "$runtime_dir/log" "$runtime_dir/ssl" "$runtime_dir/web" "$runtime_dir/conf"
|
||||
chmod 0750 "$runtime_dir/config" "$runtime_dir/data" "$runtime_dir/log" "$runtime_dir/ssl" "$runtime_dir/conf"
|
||||
|
||||
# 7. 安装 systemd 服务单元
|
||||
systemd_src="$package_root/deploy/systemd"
|
||||
if [ ! -d "$systemd_src" ] && [ -d "$runtime_dir/deploy/systemd" ]; then
|
||||
systemd_src="$runtime_dir/deploy/systemd"
|
||||
fi
|
||||
|
||||
if [ -d "$systemd_src" ]; then
|
||||
echo ">>> 正在注册 systemd 服务单元..."
|
||||
for svc in Scert.service Scert-admin.service scert-nginx.service scert-nginx.socket Scert-storage.service Scert-storage.socket; do
|
||||
if [ -f "$systemd_src/$svc" ]; then
|
||||
sed -e "s|/scert|$runtime_dir|g" "$systemd_src/$svc" > "/etc/systemd/system/$svc"
|
||||
chmod 0644 "/etc/systemd/system/$svc"
|
||||
chown root:root "/etc/systemd/system/$svc"
|
||||
fi
|
||||
done
|
||||
systemctl daemon-reload
|
||||
systemctl enable Scert.service >/dev/null 2>&1 || true
|
||||
fi
|
||||
|
||||
# 8. 检查并放行常用防火墙端口 (80, 443)
|
||||
open_firewall_ports() {
|
||||
local ports="80 443"
|
||||
echo ">>> 正在检查并自动开放网络防火墙端口 (80, 443)..."
|
||||
local opened=false
|
||||
|
||||
if command -v ufw >/dev/null 2>&1 && ufw status 2>/dev/null | grep -q "Status: active"; then
|
||||
for p in $ports; do
|
||||
ufw allow "${p}/tcp" >/dev/null 2>&1 || true
|
||||
done
|
||||
opened=true
|
||||
echo "ufw 端口放行完成 (80, 443)。"
|
||||
fi
|
||||
|
||||
if command -v firewall-cmd >/dev/null 2>&1 && systemctl is-active --quiet firewalld; then
|
||||
for p in $ports; do
|
||||
firewall-cmd --permanent --add-port="${p}/tcp" >/dev/null 2>&1 || true
|
||||
done
|
||||
firewall-cmd --reload >/dev/null 2>&1 || true
|
||||
opened=true
|
||||
echo "firewalld 端口放行并重载完成 (80, 443)。"
|
||||
fi
|
||||
|
||||
if [ "$opened" = false ] && command -v iptables >/dev/null 2>&1; then
|
||||
for p in $ports; do
|
||||
if ! iptables -C INPUT -p tcp --dport "$p" -j ACCEPT >/dev/null 2>&1; then
|
||||
iptables -I INPUT -p tcp --dport "$p" -j ACCEPT >/dev/null 2>&1 || true
|
||||
fi
|
||||
done
|
||||
echo "iptables INPUT 规则已更新放行 (80, 443)。"
|
||||
fi
|
||||
}
|
||||
|
||||
open_firewall_ports
|
||||
|
||||
# 9. 启动 Scert 服务
|
||||
echo ">>> 正在启动 Scert 主服务..."
|
||||
systemctl restart Scert.service || true
|
||||
|
||||
echo "=========================================================="
|
||||
echo " Scert 全新安装与系统服务注册完成!"
|
||||
echo " 安装路径: $runtime_dir"
|
||||
echo " 运行用户: Scert"
|
||||
echo " 开机自启: 已启用 (systemctl enable Scert)"
|
||||
echo " 服务状态: $(systemctl is-active Scert.service 2>/dev/null || echo '未运行')"
|
||||
echo "=========================================================="
|
||||
@ -1,4 +1,4 @@
|
||||
import fs from "node:fs";
|
||||
import fs from "node:fs";
|
||||
import path from "node:path";
|
||||
import crypto from "node:crypto";
|
||||
import { execFileSync } from "node:child_process";
|
||||
@ -35,6 +35,17 @@ for (const target of targets) {
|
||||
fs.rmSync(stageDir, { recursive: true, force: true });
|
||||
fs.mkdirSync(stageDir, { recursive: true });
|
||||
|
||||
// 顶层包含标准根目录 scert/
|
||||
const appDir = path.join(stageDir, "scert");
|
||||
fs.mkdirSync(appDir, { recursive: true });
|
||||
|
||||
// 预创建标准运行目录
|
||||
for (const dir of ["config", "data", "log", "ssl"]) {
|
||||
fs.mkdirSync(path.join(appDir, dir), { recursive: true });
|
||||
// 添加 .gitkeep 保持目录结构完整
|
||||
fs.writeFileSync(path.join(appDir, dir, ".gitkeep"), "", "utf8");
|
||||
}
|
||||
|
||||
const ext = goos === "windows" ? ".exe" : "";
|
||||
const binaries = [
|
||||
{ name: `scert${ext}`, pkg: "./cmd/scert" },
|
||||
@ -48,9 +59,9 @@ for (const target of targets) {
|
||||
|
||||
console.log(`Building Go binaries for ${goos}/${goarch}...`);
|
||||
const ldflags = `-s -w -X 'git.pcux.cn/xuans/Scert/backend/internal/buildinfo.Version=${versionArg.replace(/^v/i, "")}'`;
|
||||
|
||||
|
||||
for (const bin of binaries) {
|
||||
const outBin = path.join(stageDir, bin.name);
|
||||
const outBin = path.join(appDir, bin.name);
|
||||
execFileSync("go", ["build", "-trimpath", "-ldflags", ldflags, "-o", outBin, bin.pkg], {
|
||||
cwd: backendDir,
|
||||
env: {
|
||||
@ -64,43 +75,50 @@ for (const target of targets) {
|
||||
}
|
||||
|
||||
// Copy Web frontend dist
|
||||
const webDir = path.join(stageDir, "web");
|
||||
const webDir = path.join(appDir, "web");
|
||||
fs.mkdirSync(webDir, { recursive: true });
|
||||
fs.cpSync(frontendDist, webDir, { recursive: true });
|
||||
|
||||
// Generate & Copy Release Notes / 更新说明.md
|
||||
let releaseNotes = '';
|
||||
// Generate & Copy Release Notes / 更新说明.md / CHANGELOG.md
|
||||
let releaseNotes = "";
|
||||
try {
|
||||
const logOutput = execFileSync('git', ['log', '-n', '10', '--pretty=format:- %s (%h)'], { encoding: 'utf8' }).trim();
|
||||
releaseNotes = '# Scert ' + versionArg + ' 版本更新说明\n\n发布日期: ' + new Date().toISOString().slice(0, 10) + '\n\n### 本次版本主要修改与优化内容:\n\n' + logOutput + '\n';
|
||||
const logOutput = execFileSync("git", ["log", "-n", "10", "--pretty=format:- %s (%h)"], { encoding: "utf8" }).trim();
|
||||
releaseNotes = `# Scert ${versionArg} 版本更新说明\n\n发布日期: ${new Date().toISOString().slice(0, 10)}\n\n### 本次版本主要修改与优化内容:\n\n${logOutput}\n`;
|
||||
} catch {
|
||||
releaseNotes = '# Scert ' + versionArg + ' 版本更新说明\n\n- 自动化打包构建产物,支持全平台服务部署与运维。\n';
|
||||
releaseNotes = `# Scert ${versionArg} 版本更新说明\n\n- 自动化打包构建产物,支持全平台服务部署与运维。\n`;
|
||||
}
|
||||
fs.writeFileSync(path.join(stageDir, '更新说明.md'), releaseNotes, 'utf8');
|
||||
fs.writeFileSync(path.join(stageDir, 'CHANGELOG.md'), releaseNotes, 'utf8');
|
||||
fs.writeFileSync(path.join(appDir, "更新说明.md"), releaseNotes, "utf8");
|
||||
fs.writeFileSync(path.join(appDir, "CHANGELOG.md"), releaseNotes, "utf8");
|
||||
|
||||
// Copy Deploy configurations into scert/deploy/
|
||||
const appDeployDir = path.join(appDir, "deploy");
|
||||
fs.mkdirSync(appDeployDir, { recursive: true });
|
||||
|
||||
// Copy Deploy configurations
|
||||
if (fs.existsSync(path.join(deployDir, "README.md"))) {
|
||||
fs.copyFileSync(path.join(deployDir, "README.md"), path.join(stageDir, "部署说明.md"));
|
||||
fs.copyFileSync(path.join(deployDir, "README.md"), path.join(appDir, "部署说明.md"));
|
||||
fs.copyFileSync(path.join(deployDir, "README.md"), path.join(appDeployDir, "README.md"));
|
||||
}
|
||||
|
||||
if (goos === "linux") {
|
||||
if (fs.existsSync(path.join(deployDir, "install-linux.sh"))) {
|
||||
fs.copyFileSync(path.join(deployDir, "install-linux.sh"), path.join(stageDir, "install-linux.sh"));
|
||||
if (fs.existsSync(path.join(deployDir, "install-systemd.sh"))) {
|
||||
fs.copyFileSync(path.join(deployDir, "install-systemd.sh"), path.join(appDeployDir, "install-systemd.sh"));
|
||||
}
|
||||
if (fs.existsSync(path.join(deployDir, "update-systemd.sh"))) {
|
||||
fs.copyFileSync(path.join(deployDir, "update-systemd.sh"), path.join(appDeployDir, "update-systemd.sh"));
|
||||
}
|
||||
if (fs.existsSync(path.join(deployDir, "systemd"))) {
|
||||
fs.cpSync(path.join(deployDir, "systemd"), path.join(stageDir, "systemd"), { recursive: true });
|
||||
fs.cpSync(path.join(deployDir, "systemd"), path.join(appDeployDir, "systemd"), { recursive: true });
|
||||
}
|
||||
if (fs.existsSync(path.join(deployDir, "nginx"))) {
|
||||
fs.cpSync(path.join(deployDir, "nginx"), path.join(stageDir, "nginx"), { recursive: true });
|
||||
fs.cpSync(path.join(deployDir, "nginx"), path.join(appDeployDir, "nginx"), { recursive: true });
|
||||
}
|
||||
} else if (goos === "windows") {
|
||||
if (fs.existsSync(path.join(deployDir, "install-windows.ps1"))) {
|
||||
fs.copyFileSync(path.join(deployDir, "install-windows.ps1"), path.join(stageDir, "install-windows.ps1"));
|
||||
fs.copyFileSync(path.join(deployDir, "install-windows.ps1"), path.join(appDeployDir, "install-windows.ps1"));
|
||||
}
|
||||
}
|
||||
|
||||
// Generate SHA256SUMS
|
||||
// Generate SHA256SUMS for the package contents
|
||||
const allFiles = [];
|
||||
function collect(dir, base) {
|
||||
for (const item of fs.readdirSync(dir, { withFileTypes: true })) {
|
||||
@ -126,13 +144,12 @@ for (const target of targets) {
|
||||
|
||||
console.log(`Packaging ${archiveName}...`);
|
||||
if (archiveExt === "tar.gz") {
|
||||
execFileSync("tar", ["-czf", archivePath, "-C", outDir, pkgName], { stdio: "inherit" });
|
||||
execFileSync("tar", ["-czf", archivePath, "-C", stageDir, "scert", "SHA256SUMS"], { stdio: "inherit" });
|
||||
} else {
|
||||
// PowerShell Compress-Archive or tar
|
||||
try {
|
||||
execFileSync("tar", ["-a", "-c", "-f", archivePath, "-C", outDir, pkgName], { stdio: "inherit" });
|
||||
execFileSync("tar", ["-a", "-c", "-f", archivePath, "-C", stageDir, "scert", "SHA256SUMS"], { stdio: "inherit" });
|
||||
} catch {
|
||||
execFileSync("powershell", ["-Command", `Compress-Archive -Path '${stageDir}' -DestinationPath '${archivePath}' -Force`], { stdio: "inherit" });
|
||||
execFileSync("powershell", ["-Command", `Compress-Archive -Path '${path.join(stageDir, "*")}' -DestinationPath '${archivePath}' -Force`], { stdio: "inherit" });
|
||||
}
|
||||
}
|
||||
|
||||
@ -140,4 +157,4 @@ for (const target of targets) {
|
||||
const archiveHash = crypto.createHash("sha256").update(fs.readFileSync(archivePath)).digest("hex");
|
||||
fs.writeFileSync(`${archivePath}.sha256`, `${archiveHash} ${archiveName}\n`, "utf8");
|
||||
console.log(`Finished ${archiveName} (${archiveHash})`);
|
||||
}
|
||||
}
|
||||
|
||||
178
deploy/update-systemd.sh
Normal file
178
deploy/update-systemd.sh
Normal file
@ -0,0 +1,178 @@
|
||||
#!/usr/bin/env bash
|
||||
set -euo pipefail
|
||||
|
||||
# Scert 生产环境版本平滑升级脚本 (755)
|
||||
# 规范说明:
|
||||
# 1. 严格以现有生产环境的实际安装路径作为更新路径,严禁以升级包解压路径作为运行路径。
|
||||
# 2. 仅更新程序文件与系统服务,严密保留现有数据库、配置文件、证书与域名,免去重新初始化流程。
|
||||
|
||||
usage() {
|
||||
echo "用法:$0 [现有安装目录]"
|
||||
echo "默认将自动从 /etc/systemd/system/Scert.service 中解析实际安装路径(如 /scert)。"
|
||||
echo "如果服务未安装或需要手动指定,可在参数中显式传入安装目录。"
|
||||
}
|
||||
|
||||
if [ "${1:-}" = "-h" ] || [ "${1:-}" = "--help" ]; then
|
||||
usage
|
||||
exit 0
|
||||
fi
|
||||
|
||||
if [ "$(id -u)" -ne 0 ]; then
|
||||
echo "错误:必须使用 root 用户执行升级!" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
script_dir="$(cd "$(dirname "$0")" && pwd)"
|
||||
package_root="$(realpath -e -- "$script_dir/..")"
|
||||
|
||||
# 1. 自动探查并确定系统的实际安装路径
|
||||
target_dir="${1:-}"
|
||||
|
||||
if [ -z "$target_dir" ]; then
|
||||
if [ -f /etc/systemd/system/Scert.service ]; then
|
||||
service_workdir="$(grep -E '^[[:space:]]*WorkingDirectory=' /etc/systemd/system/Scert.service | head -n1 | cut -d'=' -f2- | tr -d ' ' || true)"
|
||||
if [ -n "$service_workdir" ] && [ -d "$service_workdir" ]; then
|
||||
target_dir="$service_workdir"
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
|
||||
if [ -z "$target_dir" ]; then
|
||||
for candidate in /scert /opt/scert; do
|
||||
if [ -d "$candidate" ] && [ -f "$candidate/scert" ] && [ "$candidate" != "$package_root" ]; then
|
||||
target_dir="$candidate"
|
||||
break
|
||||
fi
|
||||
done
|
||||
fi
|
||||
|
||||
if [ -z "$target_dir" ]; then
|
||||
echo "错误:未能在系统服务中检测到 Scert 的现有安装路径!" >&2
|
||||
echo "请手动指定目标安装目录,例如:$0 /scert" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
target_dir="$(realpath -m -- "$target_dir")"
|
||||
|
||||
if [ ! -d "$target_dir" ]; then
|
||||
echo "错误:目标安装目录不存在: $target_dir" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if [ ! -f "$target_dir/scert" ]; then
|
||||
echo "警告:在目标目录 $target_dir 下未检测到旧的 scert 主程序,请确认是否为正确的安装目录!"
|
||||
fi
|
||||
|
||||
echo "=========================================================="
|
||||
echo " Scert 服务平滑更新 "
|
||||
echo " 升级包解压源目录 : $package_root"
|
||||
echo " 目标系统安装目录 : $target_dir"
|
||||
echo "=========================================================="
|
||||
|
||||
case "$(uname -m)" in
|
||||
x86_64) arch=amd64 ;;
|
||||
aarch64|arm64) arch=arm64 ;;
|
||||
*) echo "不支持的系统架构: $(uname -m)" >&2; exit 1 ;;
|
||||
esac
|
||||
|
||||
# 2. 定位新版本程序二进制文件
|
||||
if [ -f "$package_root/scert" ] && [ -f "$package_root/scert-admin" ]; then
|
||||
new_scert="$package_root/scert"
|
||||
new_scert_admin="$package_root/scert-admin"
|
||||
new_scert_nginx="$package_root/scert-nginx"
|
||||
new_scert_storage="$package_root/scert-storage"
|
||||
else
|
||||
echo "错误:未能找到升级包中的二进制程序文件!" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# 3. 停止运行中的服务以解除文件占用
|
||||
echo ">>> 正在停止运行中的 Scert 服务..."
|
||||
systemctl stop Scert.service 2>/dev/null || true
|
||||
systemctl stop Scert-admin.service 2>/dev/null || true
|
||||
systemctl stop scert-nginx.service 2>/dev/null || true
|
||||
systemctl stop Scert-storage.service 2>/dev/null || true
|
||||
|
||||
# 4. 确保运行用户与组存在
|
||||
if ! getent group Scert >/dev/null; then
|
||||
groupadd --system Scert
|
||||
fi
|
||||
if ! getent passwd Scert >/dev/null; then
|
||||
useradd --system --gid Scert --home-dir "$target_dir" --shell /usr/sbin/nologin Scert
|
||||
fi
|
||||
|
||||
# 5. 替换程序二进制文件至安装目录(保持现有数据库和配置文件不被覆盖)
|
||||
echo ">>> 正在更新主程序及管理工具至: $target_dir"
|
||||
if [ "$new_scert" != "$target_dir/scert" ]; then
|
||||
cp -f "$new_scert" "$target_dir/scert"
|
||||
fi
|
||||
chown Scert:Scert "$target_dir/scert"
|
||||
chmod 0755 "$target_dir/scert"
|
||||
|
||||
if [ "$new_scert_admin" != "$target_dir/scert-admin" ]; then
|
||||
cp -f "$new_scert_admin" "$target_dir/scert-admin"
|
||||
fi
|
||||
chown root:root "$target_dir/scert-admin"
|
||||
chmod 0700 "$target_dir/scert-admin"
|
||||
|
||||
if [ -f "$new_scert_nginx" ]; then
|
||||
cp -f "$new_scert_nginx" "$target_dir/scert-nginx"
|
||||
chown root:root "$target_dir/scert-nginx"
|
||||
chmod 0755 "$target_dir/scert-nginx"
|
||||
fi
|
||||
|
||||
if [ -f "$new_scert_storage" ]; then
|
||||
cp -f "$new_scert_storage" "$target_dir/scert-storage"
|
||||
chown root:root "$target_dir/scert-storage"
|
||||
chmod 0755 "$target_dir/scert-storage"
|
||||
fi
|
||||
|
||||
# 同步更新前端静态资源 web/
|
||||
if [ -d "$package_root/web" ]; then
|
||||
echo ">>> 正在同步前端静态资源..."
|
||||
mkdir -p "$target_dir/web"
|
||||
cp -rf "$package_root/web"/* "$target_dir/web/" 2>/dev/null || true
|
||||
fi
|
||||
|
||||
# 同时更新安装目录下的 deploy 脚本供日后维护
|
||||
if [ "$package_root" != "$target_dir" ] && [ -d "$package_root/deploy" ]; then
|
||||
mkdir -p "$target_dir/deploy"
|
||||
cp -rf "$package_root/deploy"/* "$target_dir/deploy/" 2>/dev/null || true
|
||||
chmod -R 0755 "$target_dir/deploy" 2>/dev/null || true
|
||||
fi
|
||||
|
||||
# 6. 更新 systemd 服务单元
|
||||
systemd_src="$package_root/deploy/systemd"
|
||||
if [ ! -d "$systemd_src" ] && [ -d "$target_dir/deploy/systemd" ]; then
|
||||
systemd_src="$target_dir/deploy/systemd"
|
||||
fi
|
||||
|
||||
if [ -d "$systemd_src" ]; then
|
||||
for svc in Scert.service Scert-admin.service scert-nginx.service scert-nginx.socket Scert-storage.service Scert-storage.socket; do
|
||||
if [ -f "$systemd_src/$svc" ]; then
|
||||
sed -e "s|/scert|$target_dir|g" "$systemd_src/$svc" > "/etc/systemd/system/$svc"
|
||||
chmod 0644 "/etc/systemd/system/$svc"
|
||||
chown root:root "/etc/systemd/system/$svc"
|
||||
fi
|
||||
done
|
||||
fi
|
||||
|
||||
# 7. 重载 systemd 并重新启动 Scert
|
||||
echo ">>> 重载 systemd 配置并重启 Scert 服务..."
|
||||
systemctl daemon-reload
|
||||
systemctl enable Scert.service >/dev/null 2>&1 || true
|
||||
systemctl restart Scert.service
|
||||
|
||||
# 8. 检查运行状态
|
||||
sleep 1
|
||||
if systemctl is-active --quiet Scert.service; then
|
||||
echo "=========================================================="
|
||||
echo " Scert 平滑升级成功!"
|
||||
echo " 升级程序写入目录: $target_dir"
|
||||
echo " 数据库、SSL 证书及配置均完整保留。"
|
||||
echo " 服务状态: active (running)"
|
||||
echo "=========================================================="
|
||||
else
|
||||
echo "警告:Scert 服务启动异常,请检查服务日志: journalctl -u Scert -n 20 --no-pager" >&2
|
||||
exit 1
|
||||
fi
|
||||
@ -3719,7 +3719,7 @@ P0-05 从 `[!]` 调整为 `[~]`,并未标记完成;P0-04 剩余门禁和全
|
||||
|
||||
## 2026年10月18日 发布包目录架构重构与deploy部署运维套件标准化
|
||||
|
||||
- [~] 需求梳理:统一所有版本的发布包打包架构与包内目录结构,参考标准规范结构(与 Smail 部署体系规范对齐):
|
||||
- [✓] 需求梳理:统一所有版本的发布包打包架构与包内目录结构,参考标准规范结构(与 Smail 部署体系规范对齐):
|
||||
scert/
|
||||
├── config/ # 运行时配置目录
|
||||
├── data/ # 业务数据/数据库目录
|
||||
@ -3740,9 +3740,9 @@ P0-05 从 `[!]` 调整为 `[~]`,并未标记完成;P0-04 剩余门禁和全
|
||||
├── scert-nginx.socket
|
||||
├── Scert-storage.service
|
||||
└── Scert-storage.socket
|
||||
- [ ] 编写 deploy/install-systemd.sh:实现交互式全新安装部署、前置环境与端口检查、systemd 服务单元安装与平滑启用。
|
||||
- [ ] 编写 deploy/update-systemd.sh:实现生产环境版本平滑升级,严密保护现有数据库、证书与配置不被覆盖破坏。
|
||||
- [ ] 改造 deploy/package.mjs:支持生成上述标准规范层级目录,并在 Linux 环境下保留可执行脚本 755 权限。
|
||||
- [ ] 适配 .github/workflows/release.yml 与 .gitea/workflows/release.yaml 工作流,确保 CI/CD 自动发布一致。
|
||||
- [ ] 运行全量单元测试与打包验证,检查生成包目录结构与 SHA256SUMS。
|
||||
- [ ] 提交 Git 代码并双重推送到 git.pcux.cn 与 github.com。
|
||||
- [✓] 编写 deploy/install-systemd.sh:实现交互式全新安装部署、前置环境与端口检查、systemd 服务单元安装与平滑启用。
|
||||
- [✓] 编写 deploy/update-systemd.sh:实现生产环境版本平滑升级,严密保护现有数据库、证书与配置不被覆盖破坏。
|
||||
- [✓] 改造 deploy/package.mjs:支持生成上述标准规范层级目录,并在 Linux 环境下保留可执行脚本 755 权限。
|
||||
- [✓] 适配 .github/workflows/release.yml 与 .gitea/workflows/release.yaml 工作流,确保 CI/CD 自动发布一致。
|
||||
- [✓] 运行全量单元测试与打包验证,检查生成包目录结构与 SHA256SUMS。
|
||||
- [✓] 提交 Git 代码并双重推送到 git.pcux.cn 与 github.com。
|
||||
|
||||
Loading…
Reference in New Issue
Block a user