token验证(监听post和get) √
nginx反向代理隐藏端口 √
配置放到顶部,方便调整 √
同步git仓库 √
宝塔的webhook很好用,上次分享了一个在宝塔写webhook的文章,今天要在一台没有宝塔的服务器使用webhook功能,服务器已经有abc.com这样的域名在运行,所以我计划是在abc.com/webhook这样的链接访问时触发webhook拉取。然后在git仓库设置webhook回调即可。
一开始想直接用shell写的,和宝塔的一样,但是发现还是要做网络请求,于是用了netcat这个网络工具,后来发现虽然可以实现,但是并不好控制netcat,这玩意更适合用于测试网络情况。
这还不如写个go或者python呢,于是我看看服务器环境,有python没有go,那就用python吧,服务器项目是php的,不要问我为什么不用php直接执行git命令!!!
服务器的python是2.7.2,所以用python2的语法写如下(pull.py):
# -*- coding: utf-8 -*- import BaseHTTPServer import SimpleHTTPServer import urlparse import subprocess # 全局变量 WEBHOOK_TOKEN = '我是token' WEBHOOK_PORT = 8072 GIT_DIR = '/www/wwwroot/abc.com' class WebhookHandler(SimpleHTTPServer.SimpleHTTPRequestHandler): def do_GET(self): # 检查请求路径是否为/webhook if self.path.startswith('/webhook'): query_components = urlparse.urlparse(self.path).query query_params = urlparse.parse_qs(query_components) token = query_params.get('token', [''])[0] if token == WEBHOOK_TOKEN: self.handle_webhook_request() else: self.send_response(403) self.send_header('Content-type', 'text/plain') self.end_headers() self.wfile.write("Forbidden") else: self.send_response(404) self.send_header('Content-type', 'text/plain') self.end_headers() self.wfile.write("Not Found") def do_POST(self): # 检查请求路径是否为/webhook if self.path.startswith('/webhook'): query_components = urlparse.urlparse(self.path).query query_params = urlparse.parse_qs(query_components) token = query_params.get('token', [''])[0] # 如果Token通过URL传递,直接使用 if not token: # 从请求体中获取Token(假设请求体为JSON格式) content_length = int(self.headers.getheader('content-length', 0)) body = self.rfile.read(content_length) import json post_data = json.loads(body) token = post_data.get('token', '') if token == WEBHOOK_TOKEN: self.handle_webhook_request() else: self.send_response(403) self.send_header('Content-type', 'text/plain') self.end_headers() self.wfile.write("Forbidden") else: self.send_response(404) self.send_header('Content-type', 'text/plain') self.end_headers() self.wfile.write("Not Found") def handle_webhook_request(self): # 指定项目目录 project_dir = GIT_DIR # 切换到项目目录并执行git pull try: result = subprocess.Popen(['git', 'pull'], cwd=project_dir, stdout=subprocess.PIPE, stderr=subprocess.PIPE) stdout, stderr = result.communicate() # 构造响应 response = "Result of git pull in %s:\n%s\nErrors:\n%s" % (project_dir, stdout, stderr) self.send_response(200) self.send_header('Content-type', 'text/plain') self.end_headers() self.wfile.write(response) except Exception as e: self.send_response(500) self.send_header('Content-type', 'text/plain') self.end_headers() self.wfile.write("Error executing git pull: %s" % e) if __name__ == '__main__': server_address = ('', WEBHOOK_PORT) httpd = BaseHTTPServer.HTTPServer(server_address, WebhookHandler) print "Starting HTTP server on port %s..." % WEBHOOK_PORT httpd.serve_forever()
上面指定了项目目录/www/wwwroot/abc.com;指定了映射端口8072;根据实际情况自己调整哈,上面仅限测试。
接下来给这个pull.py执行权限,我就直接给775了:
chmod 775 pull.py
然后运行这个python脚本
python pull.py
出现这样的信息就是成功的:
Starting HTTP server on port 8072...
也可以后端进程的方式运行(我就用一种方式,其它的自己研究哈):
nohup python pull.py > git_pull.log 2>&1 &
重启脚本(先kill掉再启动即可)
kill -9 `ps -ef|grep pull.py|grep -v grep|awk '{print $2}'` nohup python pull.py > git_pull.log 2>&1 &
然后在nginx里的abc.com.conf配置加上反向代理:
location /webhook { proxy_pass http://localhost:8072/webhook; # 将请求转发到8072端口 proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header X-Forwarded-Proto $scheme; }
记得重启一下nginx
sudo systemctl restart nginx
然后测试效果如下
看日志也是可以知道什么时候有推送的
可以说是非常成功了。
今天到此结束,祝大家开心过每一天。