如何基于Gitolite实现Git推送后自动触发树莓派拉取代码?
嘿,我刚好折腾过类似的场景,咱们一步步来实现这个和GitHub Webhook同款的自动拉取功能,比你之前试的全局post-receive钩子要省心多了:
实现Gitolite Git服务器触发树莓派自动Git Pull的Webhook方案
一、先在树莓派上搭个Webhook接收服务
因为你的树莓派能全局访问,咱们先在这端做个轻量的HTTP服务,专门接收Git服务器的推送通知,然后自动执行git pull。不用PHP,用Python Flask就很方便,轻量还稳定。
1. 安装Flask
先给树莓派装个Flask:
sudo apt update && sudo apt install python3-flask
2. 写个Webhook处理脚本
创建一个webhook_handler.py文件,内容改成你自己的仓库路径和密钥:
from flask import Flask, request import subprocess import os app = Flask(__name__) # 替换成你树莓派上的目标仓库路径 REPO_PATH = "/home/pi/my-project-repo" # 设个密钥防恶意请求,后面Git服务器也要用这个 SECRET_TOKEN = "my-super-secret-token-123" @app.route('/webhook', methods=['POST']) def handle_webhook(): # 先验证密钥,安全第一 if request.headers.get('X-Secret-Token') != SECRET_TOKEN: return "Unauthorized", 401 # 切换到仓库目录执行pull os.chdir(REPO_PATH) try: pull_result = subprocess.run(['git', 'pull'], capture_output=True, text=True) if pull_result.returncode == 0: return f"Pull成功!输出:\n{pull_result.stdout}", 200 else: return f"Pull失败,错误信息:\n{pull_result.stderr}", 500 except Exception as e: return f"执行出错: {str(e)}", 500 if __name__ == '__main__': # 监听所有接口,端口选个你喜欢的,比如5000 app.run(host='0.0.0.0', port=5000)
3. 配置树莓派免密拉取代码
脚本要自动git pull,得让树莓派不用输密码就能从Gitolite服务器拉代码:
- 生成SSH密钥:
ssh-keygen -t ed25519(一路回车就行,不用设密码) - 把树莓派的
~/.ssh/id_ed25519.pub内容复制到Gitolite服务器的conf/gitolite.conf里,给对应仓库加上这个用户的只读权限,比如:
然后在Gitolite服务器上执行repo my-project-repo RW+ = your-local-user R = raspberry-pi-usergitolite setup加载配置。
4. 让Webhook服务后台跑
总不能一直开着终端吧,用systemd整个服务:
创建/etc/systemd/system/webhook.service文件:
[Unit] Description=Git Webhook 自动拉取服务 After=network.target [Service] User=pi WorkingDirectory=/home/pi ExecStart=/usr/bin/python3 /home/pi/webhook_handler.py Restart=always [Install] WantedBy=multi-user.target
然后启动并设为开机自启:
sudo systemctl daemon-reload sudo systemctl enable webhook sudo systemctl start webhook
记得给树莓派开对应的端口防火墙:sudo ufw allow 5000
二、给Gitolite服务器加Post-Receive钩子触发Webhook
Gitolite支持仓库级的钩子,咱们给目标仓库加个钩子,一收到推送就给树莓派发请求。
1. 写个Post-Receive钩子脚本
在Gitolite服务器的/var/lib/gitolite/hooks/common目录(如果你的安装路径不同,找对应的hooks/common目录)创建post-receive-webhook文件:
#!/bin/bash # 替换成你的树莓派IP和端口 WEBHOOK_URL="http://192.168.x.x:5000/webhook" # 和树莓派脚本里一样的密钥 SECRET_TOKEN="my-super-secret-token-123" # 只监听main分支的推送(可选,你可以改成分支名) while read oldrev newrev refname; do branch=$(git rev-parse --symbolic --abbrev-ref $refname) if [ "$branch" = "main" ]; then # 发送POST请求触发拉取 curl -X POST -H "X-Secret-Token: $SECRET_TOKEN" $WEBHOOK_URL fi done
给脚本加执行权限:chmod +x post-receive-webhook
2. 关联到目标仓库
编辑Gitolite的conf/gitolite.conf,给需要自动拉取的仓库加上钩子配置:
repo my-project-repo RW+ = your-local-user R = raspberry-pi-user config hooks.post-receive = post-receive-webhook
然后执行gitolite setup重新加载配置。
三、测试一下!
- 从本地PC推代码到Gitolite服务器
- 看树莓派的Webhook日志:
sudo journalctl -u webhook -f,能看到请求记录和pull结果 - 去树莓派的仓库目录看看,代码应该已经自动更新了
一些小提醒
- 密钥一定要设,别让随便什么请求都能触发你的
git pull - 如果树莓派上的仓库是裸仓库,记得改成非裸的(
git clone出来的就是非裸的,裸仓库没法pull) - 可以在Webhook脚本里加日志写入文件,方便排查问题
内容的提问来源于stack exchange,提问作者Usman Khan
相关产品推荐
相关产品推荐

