unnamed (2).jpg

Gitee + Linux 全自动部署系统搭建指南

版本: 1.0
环境: Nginx + PHP 8.x + Git
场景: 本地代码推送到 Gitee 后,Linux 服务器自动拉取并部署。


⚠️ 前置核心原则

  1. 敏感文件不入库:数据库配置 (config.inc.php) 和上传目录 (usr/uploads) 必须忽略。
  2. 权限分离:部署脚本由 Web 用户 (www-data) 执行,必须确保该用户有文件读写权限。
  3. 鉴权固化:在服务器端硬编码 Git 账号密码,彻底解决自动拉取时的密码验证失败问题。

第一阶段:本地开发环境准备 (Windows/Mac)

1. 配置忽略规则 (.gitignore)

在项目根目录创建 .gitignore,防止敏感文件泄露及覆盖服务器配置。

# --- 核心配置 (绝对禁止提交) ---
config.inc.php
database.php
.env

# --- 部署工具 (保护 Token) ---
webhook.php
deploy.sh

# --- 用户数据 (防止覆盖服务器图片) ---
/usr/uploads/*
!/usr/uploads/.gitkeep

# --- IDE 与系统垃圾文件 ---
.idea/
.vscode/
*.log
.DS_Store
Thumbs.db

2. 清理 Git 缓存 (重要)

如果 config.inc.php 之前已经被提交过,必须执行以下命令将其从版本库移除(保留本地文件):

git rm --cached config.inc.php
git rm --cached webhook.php
git commit -m "Security: Remove sensitive files from tracking"
git push origin master

第二阶段:服务器端 Git 配置 (Linux)

1. 初始化仓库

root 身份登录,克隆项目到 Web 根目录。

cd /var/www
# 首次克隆
git clone https://gitee.com/YOUR_USERNAME/YOUR_PROJECT.git typecho
cd typecho

2. 硬编码凭证 (解决鉴权核心)

修改 .git/config 文件,将账号密码直接写入 URL,避免脚本执行时因无交互界面而报错。

nano .git/config

找到 [remote "origin"] 部分,修改 url

[remote "origin"]
    # 格式说明:https://用户名:密码@gitee.com/用户名/项目名.git
    # ⚠️ 注意:如果密码中包含 @,必须替换为 %40 (URL编码)
    
    url = https://YOUR_PHONE_NUM:YOUR_PASSWORD@gitee.com/YOUR_USERNAME/YOUR_PROJECT.git
    
    fetch = +refs/heads/*:refs/remotes/origin/*

3. 忽略权限变更

避免 Linux/Windows 文件权限差异导致 Git 提示文件被修改。

git config core.filemode false

第三阶段:部署脚本编写

在服务器项目根目录 (/var/www/typecho/) 创建以下两个文件。

1. 执行脚本 (deploy.sh)

#!/bin/bash

# --- 配置区 ---
BRANCH="master"
LOGFILE="deploy.log"

# 切换到脚本所在目录
cd "$(dirname "$0")" || exit

log() {
    echo "[$(date '+%Y-%m-%d %H:%M:%S')] $1"
    echo "[$(date '+%Y-%m-%d %H:%M:%S')] $1" >> "$LOGFILE"
}

echo "" >> "$LOGFILE"
log "--- DEPLOY START ($BRANCH) ---"

# 1. 信任当前目录 (解决 Git 安全目录限制)
git config safe.directory "$(pwd)"

# 2. 拉取代码
log "[1/2] Pulling code..."
git checkout "$BRANCH" >> "$LOGFILE" 2>&1

# 尝试拉取,如果失败则强制重置
if git pull origin "$BRANCH" >> "$LOGFILE" 2>&1; then
    log "Git pull success."
else
    log "Git pull failed, trying force reset..."
    git fetch --all >> "$LOGFILE" 2>&1
    git reset --hard origin/"$BRANCH" >> "$LOGFILE" 2>&1
    
    if [ $? -eq 0 ]; then
        log "Force reset success."
    else
        log "Error: Force reset failed."
        exit 1
    fi
fi

# 3. 修正权限 (确保 Web 用户可读写)
log "[2/2] Fixing permissions..."
find . -type d -not -path "./.git*" -exec chmod 755 {} \;
find . -type f -not -path "./.git*" -exec chmod 644 {} \;
chmod +x deploy.sh

log "Permissions fixed."
log "--- DEPLOY FINISHED ---"
echo "Done."

2. 接收入口 (webhook.php)

<?php
// ==========================================
// Gitee WebHook Receiver
// ==========================================

// ★ 设置密钥 (必须与 Gitee 后台填写的一致)
$secret = 'YOUR_WEBHOOK_PASSWORD'; 

// 获取 Token
$headers = getallheaders();
$token = $headers['X-Gitee-Token'] ?? $_SERVER['HTTP_X_GITEE_TOKEN'] ?? '';

// 鉴权
if ($token !== $secret) {
    http_response_code(403);
    die('🚫 Access Denied');
}

// 执行部署
echo "✅ Authorized. Deploying...\n";
// 2>&1 用于捕获标准错误输出
$output = shell_exec('cd ' . __DIR__ . ' && ./deploy.sh 2>&1');
echo "<pre>$output</pre>";
?>

第四阶段:权限移交 (关键步骤)

由于之前的操作是 root 进行的,必须将文件所有权移交给 Web 服务器运行用户(通常是 www-data),否则 Webhook 触发时无权修改文件。

# 1. 修改目录所有者
chown -R www-data:www-data /var/www/typecho

# 2. 赋予脚本执行权限
chmod +x /var/www/typecho/deploy.sh

第五阶段:Gitee 后台设置

  1. 进入 Gitee 项目 -\> 管理 -\> WebHooks
  2. 添加 WebHook
  3. URL: http://你的域名或IP/webhook.php
  4. WebHook 密码/签名密钥: 填写 webhook.php 中设置的 $secret
  5. 事件: 勾选 Push
  6. 点击 添加 并点击 测试,查看是否返回 200 状态码。

第六阶段:服务保活 (防重启失效)

确保服务器重启后,Web 服务能自动拉起,保证 Webhook 可用。

# 开启服务开机自启
systemctl enable nginx
systemctl enable mysql

# 根据实际 PHP 版本开启 (如 php8.2-fpm)
systemctl enable php8.2-fpm 

第七阶段:数据库迁移与自动部署联动

1. 数据库迁移目录规范

  • 迁移脚本统一放在 Typecho 项目根目录下的 db/migrations/ 目录。
  • 文件命名建议采用时间前缀 + 描述的方式,方便排序与追踪,例如:
db/migrations/
├── 20251214_01_create_demo_migration_table.sql
├── 20251220_01_add_xxx_column.sql
└── 20251220_02_update_xxx_index.sql

2. 迁移执行入口 (migrate.php)

  • 入口脚本位于 Typecho 根目录:migrate.php
  • 其核心行为为:

    • 通过 config.inc.php 初始化 Typecho,并获取数据库对象。
    • 自动创建 schema_migrations 表,用于记录已执行的迁移文件名。
    • 只执行 db/migrations 目录下「尚未记录」的 .sql 文件。
    • 每执行成功一个迁移,就将文件名写入 schema_migrations,确保幂等性。

在服务器或本地项目根目录执行:

php migrate.php

典型输出示例:

Applied migration: 20251214_01_create_demo_migration_table.sql
Migrations complete.

如果再次执行,且没有新的迁移文件,则会直接输出:

Migrations complete.

3. 本地开发时的数据库变更流程

  1. 在本地数据库手动尝试 SQL 变更,确认无误。
  2. 将最终确认的 SQL 写入一个新的迁移文件,例如:
-- db/migrations/20251220_01_add_demo_column.sql
ALTER TABLE demo_migration_test
    ADD COLUMN demo_note varchar(255) NOT NULL DEFAULT '';
  1. 在本地 Typecho 根目录执行:
php migrate.php
  1. 确认输出中有 Applied migration: 文件名,并在数据库中验证结构已生效。
  2. 将迁移文件纳入版本控制,随代码一起推送到 Gitee。

4. 服务器端自动部署中的迁移步骤

在服务器的 deploy.sh 中,完成代码拉取和权限修复后,追加一行执行迁移脚本的命令,即可把数据库结构更新纳入「自动部署流程」。

示例片段(仅保留关键部分,注意顺序):

# 2. 拉取代码
log "[1/3] Pulling code..."
git checkout "$BRANCH" >> "$LOGFILE" 2>&1

if git pull origin "$BRANCH" >> "$LOGFILE" 2>&1; then
    log "Git pull success."
else
    log "Git pull failed, trying force reset..."
    git fetch --all >> "$LOGFILE" 2>&1
    git reset --hard origin/"$BRANCH" >> "$LOGFILE" 2>&1

    if [ $? -eq 0 ]; then
        log "Force reset success."
    else
        log "Error: Force reset failed."
        exit 1
    fi
fi

# 3. 执行数据库迁移
log "[2/3] Running database migrations..."
php migrate.php >> "$LOGFILE" 2>&1

# 4. 修正权限 (确保 Web 用户可读写)
log "[3/3] Fixing permissions..."
find . -type d -not -path "./.git*" -exec chmod 755 {} \;
find . -type f -not -path "./.git*" -exec chmod 644 {} \;
chmod +x deploy.sh

要点说明:

  • 迁移必须在「代码已经更新完成」之后执行,否则可能会出现新代码依赖的表字段尚未创建的情况。
  • 权限修复放在最后,确保迁移过程中可能产生的新文件(如日志)也有正确权限。
  • 若迁移过程中发生错误,可直接在 deploy.log 中查看 php migrate.php 的输出。

5. 推荐的整体开发与部署节奏

  • 本地开发:

    • 修改代码和 SQL。
    • 将数据库变更整理为迁移 SQL 文件,放入 db/migrations/
    • 执行 php migrate.php 测试并确认无误。
    • 提交代码和迁移文件,推送到 Gitee。
  • 服务器:

    • 由 Gitee WebHook 触发 webhook.php
    • webhook.php 调用 deploy.sh
    • deploy.sh 依次执行:拉取代码 → 运行 php migrate.php → 修正权限。

这样可以保证:代码版本、数据库结构、服务器实际运行环境三者始终保持同步,并且所有数据库变更都有清晰可追踪的迁移文件记录。


常见问题排查

  • Error: Permission denied (publickey, password)

    • 检查 .git/config 中的 URL 是否正确,密码特殊字符是否已转义。
  • Error: unable to unlink old 'xxx'Permission denied

    • 文件所有权不对。重新执行 chown -R www-data:www-data /var/www/typecho
  • Deploy.log 无记录

    • 检查 webhook.php 是否被正常访问,检查 www-data 是否有权写入 deploy.log

标签: none

仅有一条评论

  1. 1 1

    1

添加新评论