ARTICLE DETAIL

资讯详情

深耕网站建设、视觉设计与SEO优化的一线实战洞察。

还在手动部署?webhook 服务端实战指南:3 分钟配置好你的第一个自动部署 Hook

还在手动部署?webhook 服务端实战指南:3 分钟配置好你的第一个自动部署 Hook

还在手动部署?webhook 服务端实战指南:3 分钟配置好你的第一个自动部署 Hook

【免费下载链接】webhookwebhook is a lightweight incoming webhook server to run shell commands项目地址: https://gitcode.com/gh_mirrors/we/webhook

还在手动部署?每次改完代码都要 SSH 到服务器上git pull、重启服务?把这件事交给webhook吧——这是一个用 Go 编写的轻量级入站 Webhook 服务端(lightweight incoming webhook server),你只需写一个 JSON 配置文件,就能在服务器上创建 HTTP 端点(hook):外部系统一推送事件,它就按你设定的触发规则自动执行 shell 命令,并支持把请求里的头、payload、URL 参数传递给命令。

本文带你 3 分钟跑通第一个 Webhook,再用 GitHub 自动部署、Slack 斜杠命令、文件接收三个真实场景把核心配置走一遍。

先搞清楚:Webhook 到底在干嘛

传统 API 是你主动去问"有没有新消息",Webhook 反过来:事件发生时,源系统直接向你预先注册的 URL 发一个 HTTP 请求。

你不需要轮询,不需要常驻一个复杂的服务端框架。webhook 收到请求后只做四件事:解析请求头/payload/查询参数 → 校验你写的触发规则 → 满足条件就执行命令 → 按约定返回响应。

换句话说,它是一台"HTTP 请求转 shell 命令"的网关,配置即规则,规则即端点。

3 分钟跑通第一个 Webhook

先拿到程序:可以git clone https://gitcode.com/gh_mirrors/we/webhook后用 Go 构建,Ubuntu/Debian 上也可以直接sudo apt-get install webhook。

然后写一个最精简的hooks.json,只要id和execute-command两个字段就是合法配置:

[ { "id": "redeploy", // 端点路径即 /hooks/redeploy "execute-command": "/var/scripts/redeploy.sh", "command-working-directory": "/var/www" } ]

启动并用 curl 打一发请求验证:

webhook -hooks hooks.json -verbose # 默认监听 9000 端口 curl -X POST http://localhost:9000/hooks/redeploy # 返回 200 且脚本被执行即成功

看到脚本执行日志,恭喜,你的第一个 Webhook 端点已经上线了。更多启动参数(端口、热加载、日志等)见 Webhook-Parameters。

三个真实场景走一遍

场景一:GitHub 推送 master 自动部署(HMAC 签名 + 分支匹配)

需求:只有"签名正确"且"推送到 master 分支"时才触发部署脚本,把提交 ID 传给脚本。

在 仓库的 Hook 示例 基础上,关键片段只有两处。pass-arguments-to-command里用点号语法引用 payload 深层字段:

"pass-arguments-to-command": [ { "source": "payload", "name": "head_commit.id" }, { "source": "payload", "name": "pusher.name" } ], "trigger-rule": { "and": [ { "match": { "type": "payload-hmac-sha1", "secret": "mysecret", "parameter": { "source": "header", "name": "X-Hub-Signature" } } }, { "match": { "type": "value", "value": "refs/heads/master", "parameter": { "source": "payload", "name": "ref" } } } ] }

and把两条规则串起来:先用payload-hmac-sha1验签(secret 要和 GitHub 仓库设置里的一致),再精确匹配ref字段。规则还支持or、not及多层嵌套,完整语法见 Hook-Rules。

验证:在 GitHub 仓库的 Webhook 设置里填http://你的服务器:9000/hooks/redeploy并保存,GitHub 会先发一个 ping 测试;再往 master 推一次提交,-verbose日志里能看到签名校验通过、脚本带着 commit ID 执行。如果换成往dev分支推,请求会被拒(可用trigger-rule-mismatch-http-response-code自定义拒绝时的状态码)。

GitLab 没有 HMAC 机制,做法类似:用value规则匹配请求头X-Gitlab-Token,值填 GitLab 生成页面上显示的 Token 即可。

场景二:Slack 聊天群里敲个斜杠命令就触发后台任务

需求:在团队群里输入/deploy,服务器就跑部署脚本,并立即回复一句"收到了"。

在 Slack 的 Slash Commands 里把 URL 指向你的 hook 端点,配置侧重点是token 校验 + 即时响应:

{ "id": "slack-deploy", "execute-command": "/opt/slack-command.sh", "response-message": "正在执行部署,稍等…", // Slack 会立刻把它显示在群里 "trigger-rule": { "match": { "type": "value", "value": "<YOUR-GENERATED-TOKEN>", // 与 Slack 后台设置的 token 一致 "parameter": { "source": "payload", "name": "token" } } } }

Slack 发来的表单数据里自带token字段,拿它做value匹配就是最省事的鉴权。想等脚本跑完再回复完整结果,把include-command-output-in-response设为true,webhook 会等命令结束并把原始输出作为响应体返回。

验证:在群里敲/deploy,几秒内出现 "正在执行部署" 的回复,且日志中脚本确实被执行,说明链路通了。

场景三:接收文件与非 JSON 数据(base64、XML、multipart、数组)

需求:接收方可能是任意格式——二进制文件、XML、multipart 表单、顶层数组……这些都有固定套路。

文件内容传递:pass-file-to-command会把请求里的数据落到临时文件,脚本通过环境变量拿到文件路径(envname指定变量名,不指定则默认HOOK_<name>):

"pass-file-to-command": [ { "source": "payload", "name": "binary", "envname": "FILE_DATA", "base64decode": true } // 收到的 base64 字符串会先解码再落盘 ]

客户端可以这样发:jo binary=%filename.zip | curl -H "Content-Type:application/json" -X POST -d @- http://localhost:9000/hooks/file-handler,脚本里直接$FILE_DATA拿到落盘后的 zip。

其余三种格式记住三个语法即可:

  • XML payload:同名元素按数组处理,属性用-前缀、文本内容用#前缀。例如<user name="Jeff"/>对应引用路径app.users.user.0.-name,消息文本则是app.messages.message.#text。
  • 顶层 JSON 数组:webhook 会把数组包进root对象,所以第一个元素的字段要写root.0.email、第二个写root.1.email,以此类推。
  • multipart/form-data:表单的 value 部分自动进入payload作用域;若某个 part(如名为payload的文件段)本身是 JSON 字符串,声明parse-parameters-as-json让 webhook 二次解析,之后就能按普通对象引用了。

验证:用 curl 分别 POST 一段 XML、一个 JSON 数组,在-verbose日志里确认规则匹配命中的是app.users.user.0.-name、root.0.email这类路径。

一张表看懂核心配置项

字段作用示例值
idhook 端点路径,/hooks/<id>"github-deploy"
execute-command触发时执行的命令(必填)"/opt/redeploy.sh"
command-working-directory命令的工作目录"/var/www"
trigger-rule触发条件,支持and/or/not/matchHMAC 签名 + 分支匹配
pass-arguments-to-command把请求值作为命令行参数传入{"source":"payload","name":"head_commit.id"}
pass-environment-to-command把请求值作为环境变量传入{"envname":"ACTION","name":"action"}
pass-file-to-command把请求内容写成临时文件供脚本读取"base64decode": true
parse-parameters-as-json把嵌套的 JSON 字符串二次解析{"source":"payload","name":"payload"}
response-message返回给发起方的固定响应文本"部署已开始"
include-command-output-in-response等命令结束并把输出作为响应返回true
http-methods允许的 HTTP 方法["POST"]

完整字段说明以 Hook-Definition 为准,可直接参考 hooks.json.example。

安全与排障:上生产前必须做的事

安全加固清单

  1. 必须加 trigger-rule:裸端点等于"知道 URL 就能执行你命令"。优先 HMAC 签名(payload-hmac-sha1/256),无签名能力的平台用 Tokenvalue匹配,Bitbucket 这类平台则用ip-whitelist配 CIDR 网段。
  2. 密钥不落配置文件:webhook 支持-template参数把配置文件当 Go 模板渲染(仓库里有 hooks.json.tmpl.example 可参考),把 secret 放进环境变量里注入,避免明文入库。
  3. 最小权限原则:脚本用专用低权限账号跑,command-working-directory收窄到必要目录;webhook 还支持-setuid/-setgid在启动后降权。
  4. 上 HTTPS:加-secure -cert -key启用 TLS;若跑在 Nginx 等反向代理后面,注意ip-whitelist校验到的是代理 IP 而非客户端,IP 限制要放在代理层做。

排障先查这 3 处

  1. 先curl -v看状态码:401/403 一般是触发规则没匹配上(签名或 token 不对),500 说明命令执行出错了,连接本身没问题再往深里查。
  2. 打开-verbose和include-command-output-in-response:前者打印完整请求与规则求值过程,后者把命令的 stdout/stderr 直接回给你,配合include-command-output-in-response-on-error能在失败时也拿到报错内容,调试完记得关掉。
  3. 核对 payload 引用路径:嵌套对象用点号(head_commit.id)、顶层数组记得加root.前缀、XML 属性带-前缀;遇到 TraCI、Travis CI 这类把 JSON 塞在表单字段里的请求,忘了parse-parameters-as-json二次解析的话,规则永远匹配不到。

写在最后

走到这里,你已经拥有一个能自动部署、能被 Slack 指挥、能收文件的 Webhook 端点了。下一步可以试试:

  • 加-hotreload或发送kill -USR1 <pid>,改配置不重启即时生效
  • 给脚本加锁(如flock),防止 GitHub 连续推送时部署脚本并发打架
  • 用 Templates 把 secret 抽成环境变量,再配 systemd 把 webhook 跑成长驻服务

配置即规则,规则即端点——剩下的创意就交给你了。

【免费下载链接】webhookwebhook is a lightweight incoming webhook server to run shell commands项目地址: https://gitcode.com/gh_mirrors/we/webhook

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

返回列表