用 Git 打通 Flask 项目的热更新

146 阅读4分钟

在做一个 AI + Excel 数据处理的 Flask 项目时,我遇到一个实际问题:

“我本地开发调好了,如何一条命令推送到服务器,并让服务器立即生效?”

这篇文章就是一份完整实践记录,涵盖了我踩过的坑、学到的经验,以及最终稳定运行的部署策略。


✅ 第一阶段:先把 Git 通起来

我项目的部署路径在云服务器上是这样的:

 ~/traeyuexin/YuexinAI

本地则是:

 F:/traeyuexin/YuexinAI

1、本地 Git 初始化流程:

 cd F:/traeyuexin/YuexinAI
git init
git config --global user.name "Aran Tu"
git config --global user.email "aran.tu@example.com"

2、添加远程地址:

 git remote add origin root@X.XXX.XXX.XX:/root/traeyuexin/YuexinAI

⚠️ 注意:别写成 ssh://root@http://...,只需 root@ip:/路径 即可。

3、首次提交 & 推送

 git add .
git commit -m "首次提交"
git push origin master

🧰 云端接收 Git 推送

进入服务器目录:

 cd ~/traeyuexin/YuexinAI
git config receive.denyCurrentBranch updateInstead

这一步至关重要,否则服务器不会让你覆盖当前代码。


❌ 我踩过的坑:用 nohup + Flask debug 模式,以为可以热更新

最初,我使用了这条命令让 Flask 在后台运行:

 nohup python app.py > output.log 2>&1 &

由于我在 app.py 中写了:

python

app.run(debug=True)

所以每次我 git push 之后改了 .py 文件,居然真的“自动重启”了!我一度以为 Flask 真有热更新能力。

后来才知道:⚠️ 这是个“错觉”!

Flask 的 debug=True 会启用自动重启机制,但它是通过子进程实现的。
nohup 下,这会造成“主进程不退出、子进程频繁重启”,非常不稳定


✅ 第二阶段:正确做法是 post-receive + run.sh

于是我切换思路,走 “Git 推送 + 自动部署 + 安全重启” 的路线。


1、服务器端配置 Git 自动部署

进入 Git 钩子目录:

 cd ~/traeyuexin/YuexinAI/.git/hooks
nano post-receive

内容如下:

 #!/bin/bash
echo "📦 收到代码推送,开始自动部署..."
GIT_WORK_TREE=/root/traeyuexin/YuexinAI git checkout -f
cd /root/traeyuexin/YuexinAI
source venv/bin/activate
./run.sh

赋权:

 chmod +x post-receive

2、run.sh 脚本(真正的部署关键)

 #!/bin/bash
cd /root/traeyuexin/YuexinAI
source venv/bin/activate

# 杀掉旧进程,防止端口冲突或 zombie 进程
pkill -f "python app.py"

# 启动新服务
echo "🚀 正在启动 Flask..."
nohup python app.py > output.log 2>&1 &

这段脚本确保了:

  • 每次部署前都干净地杀掉旧 Flask 服务;
  • nohup 启动 Flask,让它后台常驻运行;
  • 可通过 output.log 观察运行状态。

🔥 Flask 热更新的正确理解

image.png

模式说明是否推荐
debug=True + python app.py开发环境热更新✅ 开发用
nohup python app.py + debug=True有“假象热更新”,但不稳定❌ 不推荐
Git push + post-receive + run.sh稳定安全、自动重启✅ 强烈推荐
gunicorn + supervisor生产级部署✅ 建议长期用

📁 我的 .gitignore 示例

gitignore

venv/
__pycache__/
*.pyc
*.log
.env

[本地] git push origin master
            ↓
[服务器]
post-receive 自动 checkout + run.sh
            ↓
停止旧服务 → 启动新服务 → 持久运行

现在我只需要:


git add .
git commit -m "优化了处理逻辑"
git push origin master

服务器立即更新代码、重启服务,完全无感知,部署秒生效


✅ 第三阶段: gunicorn + nginx + supervisor

Flask 项目正式上线的推荐三件套:Gunicorn + Nginx + Supervisor,适用于 Ubuntu 系统(Debian 同样通用)。

YuexinAI/
│
├── app.py
├── static/
├── templates/
├── requirements.txt
├── venv/
└── gunicorn.conf.py (可选高级配置)

思路:

  • 使用 Gunicorn 作为 WSGI 服务器,接管 Flask 应用

  • Nginx 反向代理、提供静态资源支持

  • 借助 Supervisor 进行服务托管、自动重启和日志管理

  • 最终达到:安全、可控、可恢复、适配高并发

# 安装 Gunicorn
pip install gunicorn

# 安装 nginx & supervisor
sudo apt update
sudo apt install nginx supervisor -y
cd /root/traeyuexin/YuexinAI
source venv/bin/activate
gunicorn -w 4 -b 127.0.0.1:8000 app:app

说明:

  • -w 4:启动 4 个 worker 进程(建议 = CPU 核心数 * 2 + 1)
  • -b 127.0.0.1:8000:绑定本地地址端口
  • app:app:前者为 Python 文件名(app.py),后者为 Flask 对象名

浏览器访问不到是正常的,下一步配置 nginx。

sudo nano /etc/nginx/sites-available/yuexin

内容如下:

server {
    listen 80;
    server_name your-domain.com;

    location / {
        proxy_pass http://127.0.0.1:8000;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
    }

    location /static {
        alias /root/traeyuexin/YuexinAI/static;
    }

    location /favicon.ico {
        alias /root/traeyuexin/YuexinAI/static/favicon.ico;
    }
}

然后启用配置:

sudo ln -s /etc/nginx/sites-available/yuexin /etc/nginx/sites-enabled
sudo nginx -t   # 检查配置
sudo systemctl restart nginx

Supervisor 配置 Gunicorn 守护进程

sudo nano /etc/supervisor/conf.d/yuexin.conf

内容如下:

[program:yuexin]
directory=/root/traeyuexin/YuexinAI
command=/root/traeyuexin/YuexinAI/venv/bin/gunicorn -w 4 -b 127.0.0.1:8000 app:app
autostart=true
autorestart=true
stderr_logfile=/var/log/yuexin.err.log
stdout_logfile=/var/log/yuexin.out.log
user=root
environment=PATH="/root/traeyuexin/YuexinAI/venv/bin",VIRTUAL_ENV="/root/traeyuexin/YuexinAI/venv"

启动服务:

sudo supervisorctl reread
sudo supervisorctl update
sudo supervisorctl start yuexin

查看运行状态:

sudo supervisorctl status

🔥 高级推荐(可选)

  1. 开启 https(用 Let's Encrypt)
sudo apt install certbot python3-certbot-nginx -y
sudo certbot --nginx -d your-domain.com

2. 配置 gunicorn.conf.py 文件

支持自动重载、日志分离、PID 文件管理等:

# gunicorn.conf.py
bind = "127.0.0.1:8000"
workers = 4
accesslog = '/var/log/yuexin.access.log'
errorlog = '/var/log/yuexin.error.log'
reload = False  # 上线时建议 False

Supervisor command 改成:

command=/root/traeyuexin/YuexinAI/venv/bin/gunicorn -c gunicorn.conf.py app:app
  • Gunicorn:生产级 WSGI 服务
  • Nginx:统一入口 + 静态文件 + 反向代理
  • Supervisor:自动启动 + 异常重启 + 日志持久化

最后的思考

部署从来不是一件简单事,尤其是当你想把开发体验延伸到云端时。
但一旦打通 Git 推送 + 自动更新 + 安全运行这条链路,你就再也回不去手动上传/重启的日子了。