Initial commit: MyBlog full stack blog

This commit is contained in:
2026-08-22 22:28:41 +08:00
commit c61193f2af
64 changed files with 7290 additions and 0 deletions
+94
View File
@@ -0,0 +1,94 @@
# ============================================================
# MyBlog 一键更新脚本(在 Windows 上运行)
# 作用:打包本地代码 -> 上传到服务器 -> 服务器自动 备份/迁移/重启/验证
# 前置条件:
# 1. 已配置 SSH 免密登录(首次需执行:ssh-keygen 后 ssh-copy-id 服务器)
# 2. 服务器上已按 deploy/DEPLOY.md 完成首次部署(myblog 服务存在)
# 用法(在项目根目录 D:\MyBlog 打开 PowerShell):
# powershell -ExecutionPolicy Bypass -File .\deploy\update.ps1
# 或直接指定服务器:.\deploy\update.ps1 -Server root@8.145.36.108
# 常用参数:
# -Server 服务器地址,默认读取 deploy/deploy.conf(缺省用 root@8.145.36.108
# -IncludeUploads 同时同步本地 uploads/(首次部署或新增静态资源时用)
# 安全说明:
# - 永远不打包 .env 与 backend/blog.db(密钥与数据库只在服务器上)
# - 默认排除 uploads/:网页上传的文件只在服务器,本地打包不覆盖
# ============================================================
param(
[string]$Server = "",
[switch]$IncludeUploads
)
$ErrorActionPreference = "Stop"
$ScriptDir = $PSScriptRoot # deploy 目录
$ProjectRoot = Split-Path -Parent $ScriptDir # 项目根目录
$PackageName = "myblog.tar.gz"
$RemoteScript = "update_server.sh"
function Write-Step([string]$msg) { Write-Host ""; Write-Host "== $msg ==" -ForegroundColor Cyan }
# ---------- 1. 确定服务器地址(命令行参数 > deploy.conf > 默认值) ----------
if (-not $Server -and (Test-Path (Join-Path $ScriptDir "deploy.conf"))) {
$confLine = Get-Content (Join-Path $ScriptDir "deploy.conf") | Where-Object { $_ -match '^\s*SERVER\s*=' } | Select-Object -First 1
if ($confLine) { $Server = ($confLine -split '=', 2)[1].Trim() }
$domainLine = Get-Content (Join-Path $ScriptDir "deploy.conf") | Where-Object { $_ -match '^\s*DOMAIN\s*=' } | Select-Object -First 1
if ($domainLine) { $Domain = ($domainLine -split '=', 2)[1].Trim() }
}
if (-not $Server) { $Server = "root@8.145.36.108" }
Write-Host "目标服务器:$Server"
if ($Domain) { Write-Host "验证域名:$Domain" }
# ---------- 2. 检查依赖工具 ----------
foreach ($tool in @("tar", "scp", "ssh")) {
if (-not (Get-Command $tool -ErrorAction SilentlyContinue)) {
throw "缺少工具 $tool,请先安装 OpenSSH 客户端(Windows 设置 -> 可选功能)。"
}
}
# ---------- 3. 打包本地代码(排除密钥/数据库/缓存/上传目录) ----------
Write-Step "打包本地代码"
$tmpPkg = Join-Path $env:TEMP $PackageName
if (Test-Path $tmpPkg) { Remove-Item -LiteralPath $tmpPkg -Force }
Push-Location $ProjectRoot
try {
# 排除本地敏感运行数据:数据库、密钥配置、IPWatch 家庭端密钥与日志
$excludes = @("--exclude=backend/blog.db", "--exclude=backend/__pycache__",
"--exclude=backend/routers/__pycache__",
"--exclude=backend/services/__pycache__", "--exclude=venv",
"--exclude=deploy/ipwatch/ipwatch.conf",
"--exclude=deploy/ipwatch/lastip.txt",
"--exclude=deploy/ipwatch/ipwatch.log")
if (-not $IncludeUploads) { $excludes += "--exclude=uploads" }
$targets = @("frontend", "backend", "deploy", "requirements.txt", ".env.example", "README.md")
& tar -czf $tmpPkg @excludes @targets
if ($LASTEXITCODE -ne 0) { throw "tar 打包失败" }
} finally {
Pop-Location
}
# 校验包内不含敏感文件(防止配置写错把密钥带上服务器)
$bad = tar -tzf $tmpPkg | Select-String "(^|/)\.env$|blog\.db|__pycache__|^uploads/|ipwatch\.(conf|log)$|lastip\.txt" | Select-Object -First 5
if ($bad) { throw "更新包内含不应上传的文件:$($bad -join ', ')" }
Write-Host ("更新包已生成:{0}{1:N0} KB" -f $tmpPkg, ((Get-Item $tmpPkg).Length / 1KB))
# ---------- 4. 上传到服务器 ----------
Write-Step "上传更新包与服务器脚本"
& scp -o BatchMode=yes -o StrictHostKeyChecking=accept-new $tmpPkg "$($Server):/tmp/$PackageName"
if ($LASTEXITCODE -ne 0) { throw "上传失败:请确认已配置 SSH 免密登录" }
& scp -o BatchMode=yes (Join-Path $ScriptDir $RemoteScript) "$($Server):/tmp/$RemoteScript"
if ($LASTEXITCODE -ne 0) { throw "上传服务器脚本失败" }
Write-Host "上传完成"
# ---------- 5. 执行服务器端更新(备份/解压/迁移/重启/验证) ----------
Write-Step "执行服务器端更新(备份、迁移、重启、验证)"
$domainArg = if ($Domain) { " '$Domain'" } else { "" }
# 服务器端脚本若带 Windows 换行(CRLF)会导致 bash 解析失败,先统一转成 LF 再执行
& ssh -o BatchMode=yes $Server "sed -i 's/\r`$//' /tmp/$RemoteScript && bash /tmp/$RemoteScript$domainArg"
if ($LASTEXITCODE -ne 0) {
Write-Host "服务器端更新失败,请检查上方输出。可用备份回滚:/root/blog-backups/" -ForegroundColor Red
exit 1
}
Write-Host ""
Write-Host "✅ 更新完成!请打开 https://$Domain 验证。" -ForegroundColor Green