categories: 技术 需求操作文档

tags: 技术 需求操作文档 go CSDN


一、服务功能与背景

1. 核心功能

  • 定时将 Windows 本地的 Git 仓库与远端仓库同步(定期执行 git pull,检测并提交本地变更并推送到到远程)
  • 日志自动管理(临时写入释放、大文件轮转、过期清理)
  • 支持作为 Windows 服务或通过任务计划程序运行,实现后台常驻运行,无需手动执行

2. 背景与适用场景

在多设备协作开发、服务器端自动备份等场景中,手动执行 git pull/push 操作不仅繁琐,还可能因遗漏导致代码版本不一致。本工具通过 Go 语言开发,专为 Windows 环境设计,旨在实现 Git 仓库的全自动化同步,解决以下问题

  • 多设备间代码同步不及时导致的协作冲突
  • 手动操作易遗忘、效率低的问题
  • 无人值守场景下的代码自动备份需求
  • 需长期稳定运行的后台同步任务管理

二、服务直接使用方法

1. 先决条件

  • Windows 操作系统(Windows Server 2016+ / Windows 10+)
  • 已安装并可在 PATH 中访问的 git
  • 已配置 SSH 密钥实现与远程仓库的免密连接(见后续详细步骤)

2. 快速获取与编译

2.1 编译可执行文件

在项目目录运行:

go build -o git-sync-service.exe main.go

或使用仓库自带脚本:

.\build.bat

若修改依赖后请运行:

go mod tidy

核心依赖:gopkg.in/ini.v1(配置解析)、github.com/robfig/cron/v3(定时任务)、github.com/kardianos/service(Windows 服务化)。

2.2 配置文件设置

编辑同目录下的 config.ini,设置必要参数:

[Git]
# 本地Git仓库路径(必须是已初始化的Git仓库,含.git目录)
RepoPath = F:/AllMyMarkdowns/gitcode
# 日志文件路径(服务运行日志输出位置)
LogPath  = F:/AllMyMarkdowns/autoPushGit_log/git_sync_new.log
# 定时同步表达式(Cron格式,5字段:分 时 日 月 周)
CronExpr = */1 * * * *
# 可选:SSH私钥路径(用于免密连接远程仓库)
PrivateKey = C:/Users/Administrator/.ssh/id_rsa
配置项格式要求示例默认值
RepoPath本地绝对路径,需存在.git目录D:\Projects\test-repo无(必须配置)
LogPath绝对路径(目录不存在会自动创建)D:\Logs\git-sync.log无(必须配置)
CronExprCron标准表达式每5分钟:*/5 * * * *;每天23点:0 23 * * *0 * * * *(每小时)
PrivateKeySSH私钥绝对路径C:\Users\user\.ssh\id_rsa无(可选)

3. 运行方式选择

3.1 作为 Windows 服务运行

安装(需管理员权限):

.\git-sync-service.exe install
# 或使用脚本:
.\install_service.bat

启动服务:

net start GitAutoSyncService

卸载:

.\git-sync-service.exe remove
# 或使用脚本:
.\uninstall_service.bat

注意事项

  • 服务默认以 LocalSystem 身份运行,可能无法访问用户级 SSH agent
  • 若需使用用户凭证,需以指定用户身份安装服务
  • 可通过 sc query GitAutoSyncService 查看服务状态
3.2 使用任务计划程序(推荐)

仓库中提供了 install_task.bat 脚本(在「任务计划程序」中创建任务 GitAutoSyncTask,触发条件:系统启动与用户登录,运行身份:SYSTEM)。

安装(需管理员权限):

.\install_task.bat

删除任务:

.\uninstall_task.bat

手动创建任务

在「任务计划程序」中创建任务,选择以当前用户运行(可使用用户 SSH agent,但需用户登录后才运行)。

4. 日志与排查

  • 日志位置:config.iniLogPath 指定的路径
  • 服务启动失败:查看 Windows 事件查看器和日志文件
  • Git 凭证问题:以目标账户手动运行 git pull/git push 复现并排查错误

5. 两种运行方式对比

特性服务方式任务计划方式
无人登录运行支持不支持(依赖用户登录)
账号管理复杂(需配置服务运行身份)灵活(可选择当前用户)
安装难度稍高较低
适用场景服务器无人值守个人电脑脑或需用户凭证场景

三、服务详细搭建过程(开发实现)

1. 前置准备

1.1 环境要求
依赖项要求说明
Go环境1.18+需配置GOROOT、GOPATH环境变量
Git客户端任意稳定版本需添加至系统PATH(支持命令行直接执行git命令)
Windows系统Windows Server 2016+ / Windows 10+服务化依赖Windows API
SSH密钥已配置用于免密连接Git远程仓库(如GitHub、GitLab)
1.2 SSH 密钥配置(关键步骤)
1.2.1 生成 SSH 密钥

打开命令行(管理员身份),执行以下命令生成密钥(默认路径:C:\Users\用户名\.ssh\):

ssh-keygen -t rsa -b 4096 -C "my-email@example.com"
  • 执行过程中全部回车(默认无密码,避免服务运行时需要输入密钥密码)
1.2.2 配置远程仓库公钥
  1. 打开生成的公钥文件:C:\Users\用户名\.ssh\id_rsa.pub
  2. 复制文件内容(完整字符串,不含换行)
  3. 登录远程 Git 仓库(如 GitHub),进入「Settings → SSH and GPG keys → New SSH key」
  4. 粘贴公钥内容,保存即可(实现免密拉取/推送)
1.3 Go 环境配置
1.3.1 环境变量验证

执行以下命令,确保 Go 环境配置正常:

go version  # 输出Go版本(需1.18+)
go env      # 查看GOROOT、GOPATH配置
1.3.2 切换 Go 第三方源(解决依赖下载慢/失败)

因默认 Go 模块源(proxy.golang.org)国内访问不稳定,需切换至国内源:

# 永久设置国内源(阿里云)
go env -w GOPROXY=https://goproxy.cn,direct
# 允许访问私有仓库(如公司内部Git仓库,可选)
go env -w GOPRIVATE=*.your-company-domain.com

2. 项目结构与文件清单

git-sync-service/
├── main.go           # 服务核心代码
├── config.ini        # 配置文件
├── install_service.bat  # 服务安装脚本
├── uninstall_service.bat # 服务卸载脚本
├── install_task.bat    # 任务计划安装脚本
├── uninstall_task.bat  # 任务计划卸载脚本
├── build.bat          # 编译脚本
└── go.mod             # 依赖管理文件
文件名作用备注
main.go服务核心代码包含同步逻辑、服务化、日志管理等
config.ini配置文件需手动创建,配置仓库路径、日志路径等
install_service.bat服务安装脚本一键安装服务(需管理员身份运行)
uninstall_service.bat服务卸载脚本一键卸载服务(需管理员身份运行)
install_task.bat/uninstall_task.bat任务计划管理脚本用于创建/删除定时任务
git-sync-service.exe编译后的可执行文件服务运行核心程序

3. 核心代码实现思路

3.1 配置加载模块(基于gopkg.in/ini.v1
// 配置结构体定义
type Config {
    RepoPath   本地仓库路径
    LogPath    日志文件路径
    CronExpr   定时任务表达式
    PrivateKey SSH私钥路径
    ExeDir     程序运行目录
}

// 加载配置文件
func loadConfig(exeDir string) (Config, error) {
    1. 检查config.ini是否存在
    2. 使用ini库读取配置文件内容
    3. 解析并验证各配置项(路径有效性、Cron表达式格式)
    4. 处理私钥路径(检查文件存在性,过滤无效路径)
    5. 返回结构化配置对象
}
3.2 Git 同步逻辑
// Git同步主函数
func (s *GitSyncService) syncGit() {
    1. 记录同步开始日志
    2. 设置同步超时时间(防止无限阻塞)
    3. 检查仓库是否为Git仓库(验证.git目录存在)
    4. 执行git pull拉取远程变更(调用runGitCmd)
    5. 检查本地变更并提交推送(调用checkAndCommit)
    6. 处理同步结果(成功/失败/超时日志)
}

// 执行Git命令通用函数
func (s *GitSyncService) runGitCmd(ctx context.Context, cmd string, timeout time.Duration, args ...string) error {
    1. 构建完整Git命令(如git pull、git add等)
    2. 设置命令运行目录为本地仓库路径
    3. 配置Windows隐藏窗口参数(避免闪烁)
    4. 若指定私钥,设置GIT_SSH_COMMAND环境变量
    5. 执行命令并捕获输出
    6. 返回命令执行结果(错误信息包含输出内容)
}

// 检查变更并提交推送
func (s *GitSyncService) checkAndCommit(ctx context.Context) error {
    1. 执行git status --porcelain检查本地变更
    2. 若未检测到变更,刷新Git索引后再次检查
    3. 若存在变更:
        a. 执行git add .暂存所有变更
        b. 生成包含时间戳的自动提交信息
        c. 执行git commit提交变更
        d. 执行git push推送到远程仓库
    4. 返回执行过程中的错误信息
}
3.3 定时任务(基于github.com/robfig/cron/v3
import (
    "github.com/robfig/cron/v3"
)

// 启动定时任务
func startCron(cfg *Config, log *Logger) {
    1. 初始化cron调度器
    2. 添加定时任务(使用配置中的Cron表达式)
    3. 任务执行逻辑:调用Git同步函数并记录日志
    4. 启动调度器
}
3.4 Windows服务化(基于github.com/kardianos/service
// 服务核心结构体
type GitSyncService struct {
    cron    定时任务实例
    ctx     上下文对象(用于控制服务生命周期)
    cancel  取消函数
    wg      等待组(用于优雅关闭)
}

// 服务启动逻辑
func (s *GitSyncService) Start(service service.Service) error {
    1. 记录服务启动日志
    2. 初始化上下文和等待组
    3. 延迟初始化定时任务(避免服务启动阻塞)
    4. 添加同步任务到cron调度器(包含配置的Cron表达式)
    5. 启动定时任务调度器
}

// 服务停止逻辑
func (s *GitSyncService) Stop(service service.Service) error {
    1. 记录服务停止日志
    2. 触发上下文取消信号
    3. 停止定时任务调度器
    4. 等待所有同步任务完成
    5. 记录服务已停止日志
}
3.5 日志轮转与过期清理
// 日志管理任务(定时执行)
func startLogManageTask() {
    1. 创建每小时执行一次的定时器
    2. 循环执行:
        a. 调用rotateLog()进行日志轮转
        b. 调用deleteExpiredLogs()清理过期日志
        c. 记录管理过程中的错误信息
}

// 日志轮转函数
func rotateLog() error {
    1. 检查当前日志文件大小
    2. 若超过最大限制:
        a. 将当前日志重命名为带时间戳的历史文件
        b. 创建新的空日志文件
    3. 返回执行过程中的错误
}

// 删除过期日志文件
func deleteExpiredLogs() error {
    1. 遍历日志目录下的文件
    2. 筛选出符合命名规则的历史日志文件
    3. 删除超过保留期限的日志文件
    4. 返回执行过程中的错误
}

4. 编译与部署步骤

4.1 下载依赖

进入项目目录,执行以下命令下载第三方依赖:

# 下载配置解析依赖
go get gopkg.in/ini.v1
# 下载定时任务依赖
go get github.com/robfig/cron/v3
# 下载Windows服务化依赖
go get github.com/kardianos/service
4.2 编译可执行文件
go build -o git-sync-service.exe main.go
  • 编译成功后,目录下会生成git-sync-service.exe文件(大小约5-10MB)
  • 若编译报错,检查:① Go版本是否达标;② 依赖是否下载完成;③ 代码无语法错误

5. 常见问题排查

5.1 服务安装失败
  • 可能原因:未以管理员身份运行脚本、服务名冲突、可执行文件缺失
  • 解决步骤
    1. 重新以管理员身份运行安装脚本
    2. 若提示“服务已存在”,先执行卸载脚本再安装
    3. 检查git-sync-service.exe是否存在于脚本同级目录
5.2 服务启动后不同步
  • 可能原因:Cron 表达式错误、仓库路径错误、SSH 密钥配置错误、网络问题
  • 解决步骤
    1. 查看日志文件(LogPath 配置路径),搜索 “sync failed” 或错误信息
    2. 验证 Git 仓库路径:cd RepoPath && git status
    3. 验证 SSH 连接:ssh -T git@github.com(GitHub 示例)
    4. 验证 Cron 表达式:使用在线工具(如 https://crontab.guru/)检查格式
5.3 Git 拉取/推送失败
  • 可能原因:远程仓库地址变更、存在冲突、SSH 密钥错误、Git 未添加至 PATH
  • 解决步骤
    1. 检查远程地址:git remote -v
    2. 手动执行git pull 解决冲突
    3. 验证SSH密钥:ssh -i 私钥路径 git@远程仓库地址
    4. 验证Git命令:git --version

6. 服务管理与维护

6.1 手动管理命令
# 启动服务
net start GitAutoSyncService

# 停止服务
net stop GitAutoSyncService

# 查看服务状态
sc query GitAutoSyncService

# 强制删除服务(适用于卸载脚本失败时)
sc delete GitAutoSyncService
6.2 代码更新步骤
  1. 修改main.go代码(如调整同步逻辑、日志规则)
  2. 重新编译:go build -o git-sync-service.exe main.go
  3. 停止服务:net stop GitAutoSyncService
  4. 替换旧的git-sync-service.exe文件
  5. 启动服务:net start GitAutoSyncService
6.3 配置更新步骤
  1. 编辑config.ini文件(修改仓库路径、Cron 表达式等)
  2. 停止服务:net stop GitAutoSyncService
  3. 启动服务:net start GitAutoSyncService(配置仅在服务启动时加载)

总结

本服务通过 Go 语言实现 Windows 环境下的 Git 自动同步,核心优势在于:

  • 自动化:无需手动操作,定时完成拉取/提交/推送
  • 稳定性:服务化运行,后台常驻,崩溃可自动重启
  • 灵活性:支持自定义同步频率、日志路径、仓库路径
  • 无占用:日志采用临时写入模式,可随时操作日志文件

按照文档配置后,即可实现代码的全自动化同步,适用于多设备协作、服务器自动备份等场景。若遇到问题,优先查看日志文件中的错误信息,或参考「常见问题排查」章节。

更多推荐