建站手记HexoHexo 博客源文件自动备份与一键推送指南
時光本文章介绍如何通过脚本自动备份并提交Hexo源码文件,包括 source,scaffolds,themes目录文件,及
package.json,_config.yml等文件,当然,需要的话也可备份博客主目录下所有目录及文件。如果想要了解更多关于Hexo目录结构的内容,可以参阅文章Hexo 目录结构。
自动备份
创建一个私有仓库用于存放Hexo源码文件,例如 blog_source
在博客主目录创建一个.ps1(powershell脚本)后缀的文件,例如 backup.ps1,粘贴下面的代码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132
| [Console]::OutputEncoding = [System.Text.Encoding]::UTF8
$HEXO_SOURCE_DIR = "D:\WorkSpace\Blog\blog" $BACKUP_DIR = "D:\WorkSpace\Github\shiguang-coding\blog_source"
$startTime = Get-Date Write-Host "" Write-Host "========================================" -ForegroundColor Cyan Write-Host " Hexo 博客源文件备份 " -ForegroundColor Cyan Write-Host "========================================" -ForegroundColor Cyan Write-Host "开始时间:$($startTime.ToString('yyyy-MM-dd HH:mm:ss'))" -ForegroundColor Yellow Write-Host ""
Write-Host "源目录:$HEXO_SOURCE_DIR" -ForegroundColor Green Write-Host "备份到:$BACKUP_DIR" -ForegroundColor Green Write-Host ""
Write-Host "正在检查备份目录..." -ForegroundColor White if (!(Test-Path -Path $BACKUP_DIR)) { Write-Host " -> 目录不存在,正在创建..." -ForegroundColor Gray New-Item -ItemType Directory -Path $BACKUP_DIR -Force | Out-Null Write-Host " [完成] 目录已创建" -ForegroundColor Green } else { Write-Host " [完成] 目录已存在" -ForegroundColor Green } Write-Host ""
$excludeDirs = @("node_modules", ".deploy_git", ".idea", "public", ".git")
function Get-FileList($dir) { Get-ChildItem -Path $dir -Recurse -File -ErrorAction SilentlyContinue | Where-Object { $rel = $_.FullName.Substring($dir.Length + 1) $excluded = $false foreach ($d in $excludeDirs) { if ($rel -eq "db.json" -or $rel.StartsWith($d + [IO.Path]::DirectorySeparatorChar) -or $rel.StartsWith($d + "/")) { $excluded = $true break } } -not $excluded } | ForEach-Object { $rel = $_.FullName.Substring($dir.Length + 1) [PSCustomObject]@{ Path = $rel Size = $_.Length Time = $_.LastWriteTime } } }
Write-Host "正在检查变更..." -ForegroundColor White Write-Host ""
$srcFiles = Get-FileList $HEXO_SOURCE_DIR $bakFiles = Get-FileList $BACKUP_DIR
$srcMap = @{}; $srcFiles | ForEach-Object { $srcMap[$_.Path] = $_ } $bakMap = @{}; $bakFiles | ForEach-Object { $bakMap[$_.Path] = $_ }
$newFiles = @() foreach ($f in $srcFiles) { if (-not $bakMap.ContainsKey($f.Path)) { $newFiles += $f.Path } }
$deletedFiles = @() foreach ($f in $bakFiles) { if (-not $srcMap.ContainsKey($f.Path)) { $deletedFiles += $f.Path } }
$modifiedFiles = @() foreach ($f in $srcFiles) { if ($bakMap.ContainsKey($f.Path)) { $bak = $bakMap[$f.Path] if ($f.Size -ne $bak.Size -or $f.Time -ne $bak.Time) { $modifiedFiles += $f.Path } } }
if ($newFiles.Count -gt 0) { foreach ($f in $newFiles) { Write-Host " [新增] $f" -ForegroundColor Green } } if ($modifiedFiles.Count -gt 0) { foreach ($f in $modifiedFiles) { Write-Host " [修改] $f" -ForegroundColor Yellow } } if ($deletedFiles.Count -gt 0) { foreach ($f in $deletedFiles) { Write-Host " [删除] $f" -ForegroundColor Red } } if ($newFiles.Count -eq 0 -and $modifiedFiles.Count -eq 0 -and $deletedFiles.Count -eq 0) { Write-Host " 没有检测到变更" -ForegroundColor Gray }
Write-Host "" Write-Host "正在同步文件..." -ForegroundColor White Write-Host " 排除:node_modules、.deploy_git、.idea、public、.git、db.json" -ForegroundColor Gray Write-Host ""
& robocopy $HEXO_SOURCE_DIR $BACKUP_DIR /E /PURGE /XD node_modules .deploy_git .idea public .git /XF db.json /NJH /NJS /NP /NFL /NDL | Out-Null
Write-Host "" Write-Host "========================================" -ForegroundColor Cyan if ($LASTEXITCODE -le 8) { $endTime = Get-Date $duration = $endTime - $startTime Write-Host "[完成] 备份成功!" -ForegroundColor Green Write-Host " 结果:新增 $($newFiles.Count) 个 / 修改 $($modifiedFiles.Count) 个 / 删除 $($deletedFiles.Count) 个" -ForegroundColor White Write-Host " 耗时:$($duration.TotalSeconds.ToString('F1')) 秒" -ForegroundColor Yellow } else { Write-Host "[失败] 备份出错!" -ForegroundColor Red Write-Host " 错误码:$LASTEXITCODE" -ForegroundColor Red } Write-Host "========================================" -ForegroundColor Cyan Write-Host ""
|
修改脚本中Hexo博客源码目录 $HEXO_SOURCE_DIR和 备份目录 $BACKUP_DIR
打开 powershell 终端 ,执行 backup.ps1 如果当前目录已存在则覆盖(只会覆盖目录中已存在的文件,源码目录原来存在,但是博客主目录不存在的文件不受影响)

控制台会打印备份的文件详情及相关统计信息

自动提交
在源码仓库所在目录创建 push.ps1文件,粘贴以下代码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112
| $scriptPath = Split-Path -Parent $MyInvocation.MyCommand.Path
$repoPath = "D:\WorkSpace\Github\shiguang-coding\blog_source"
$startTime = Get-Date Write-Host "" Write-Host "========================================" -ForegroundColor Cyan Write-Host " Hexo 博客源文件推送 " -ForegroundColor Cyan Write-Host "========================================" -ForegroundColor Cyan Write-Host "开始时间:$($startTime.ToString('yyyy-MM-dd HH:mm:ss'))" -ForegroundColor Yellow Write-Host ""
Write-Host "仓库目录:$repoPath" -ForegroundColor Green Write-Host ""
Write-Host "正在切换到仓库目录..." -ForegroundColor White Set-Location -Path $repoPath Write-Host " [完成] 目录已切换" -ForegroundColor Green Write-Host ""
Write-Host "正在检查变更..." -ForegroundColor White git config core.quotepath false $status = git status --porcelain
if ($status) { $changeCount = ($status | Measure-Object -Line).Lines Write-Host " 发现 $changeCount 个文件有变更" -ForegroundColor Yellow Write-Host ""
$newFiles = @() $modFiles = @() $delFiles = @()
foreach ($line in $status) { $code = $line.Substring(0, 2).Trim() $file = $line.Substring(3) switch ($code) { "A" { $newFiles += $file } "M" { $modFiles += $file } "D" { $delFiles += $file } "?" { $newFiles += $file } default { if ($code -match "A") { $newFiles += $file } elseif ($code -match "D") { $delFiles += $file } else { $modFiles += $file } } } }
if ($newFiles.Count -gt 0) { Write-Host " 新增($($newFiles.Count) 个):" -ForegroundColor Green $newFiles | Select-Object -First 15 | ForEach-Object { Write-Host " + $_" -ForegroundColor Green } if ($newFiles.Count -gt 15) { Write-Host " ... 还有 $($newFiles.Count - 15) 个" -ForegroundColor Gray } } if ($modFiles.Count -gt 0) { Write-Host " 修改($($modFiles.Count) 个):" -ForegroundColor Yellow $modFiles | Select-Object -First 15 | ForEach-Object { Write-Host " ~ $_" -ForegroundColor Yellow } if ($modFiles.Count -gt 15) { Write-Host " ... 还有 $($modFiles.Count - 15) 个" -ForegroundColor Gray } } if ($delFiles.Count -gt 0) { Write-Host " 删除($($delFiles.Count) 个):" -ForegroundColor Red $delFiles | Select-Object -First 15 | ForEach-Object { Write-Host " - $_" -ForegroundColor Red } if ($delFiles.Count -gt 15) { Write-Host " ... 还有 $($delFiles.Count - 15) 个" -ForegroundColor Gray } } Write-Host ""
Write-Host "正在暂存文件..." -ForegroundColor White git add . 2>$null Write-Host " [完成] 文件已暂存" -ForegroundColor Green Write-Host ""
$currentTime = Get-Date -Format "yyyy-MM-dd HH:mm:ss" $commitMessage = "Auto commit at $currentTime"
Write-Host "正在提交..." -ForegroundColor White git commit -m $commitMessage 2>$null Write-Host " [完成] 已提交" -ForegroundColor Green Write-Host " 提交信息:$commitMessage" -ForegroundColor Yellow Write-Host ""
Write-Host "正在推送到远程..." -ForegroundColor White git push origin main 2>$null Write-Host " [完成] 已推送" -ForegroundColor Green } else { Write-Host " 没有检测到变更" -ForegroundColor Yellow Write-Host " 所有文件已是最新状态" -ForegroundColor Gray }
Write-Host "" Write-Host "========================================" -ForegroundColor Cyan $endTime = Get-Date $duration = $endTime - $startTime Write-Host "[完成] 操作结束" -ForegroundColor Green Write-Host " 耗时:$($duration.TotalSeconds.ToString('F1')) 秒" -ForegroundColor Yellow Write-Host "========================================" -ForegroundColor Cyan Write-Host ""
Set-Location -Path $scriptPath
|
当然,你也可以指定仓库目录,这样就可以在任意位置执行脚本了
1 2 3 4 5 6 7 8 9
|
$repoPath = "D:\WorkSpace\Github\shiguang-coding\blog_source"
|
直接执行push.ps1可执行文件即可

这段脚本其实就是执行了 git add ., git commit -m [commitMessage],git push origin main
如果你的仓库住分支不是main分支,可自行调整
执行该脚本将自动提交代码到远程仓库
数据恢复
- 克隆源码仓库到本地
- 执行
npm install 或者 cnpm install 安装依赖
- 执行
hexo clean && hexo g && hexo s 生成网页文件并运行
- 浏览器访问
http://localhost:4000
小贴士
如果执行过程中报错,可尝试清除npm缓存并删除node_moduls目录,重新执行npm install安装依赖
清除npm命令如下
脚本升级说明
相比初版脚本,当前版本做了以下改进:
backup.ps1 升级:
- 所有输出改为中文,方便理解
- 同步前自动检测源目录与备份目录的差异
- 按
[新增]、[修改]、[删除] 三种类型分类显示变更文件
- 显示完整的相对路径(如
source/_posts/xxx.md)
- 结束时统计新增、修改、删除数量和耗时
- robocopy 使用静默模式,不输出冗余的目录层级信息
push.ps1 升级:
- 所有输出改为中文
- 设置
core.quotepath false 解决中文文件名显示为转义字符的问题
- 将变更文件按
新增(+)、修改(~)、删除(-)分类显示
- 每类最多显示 15 个文件,超出部分显示省略
- 添加耗时统计