Webhook:把一次 HTTP POST 变成一条 shell 命令,5 分钟跑通
【免费下载链接】webhookwebhook is a lightweight incoming webhook server to run shell commands项目地址: https://gitcode.com/gh_mirrors/we/webhook
webhook 是一个用 Go 写的轻量级入站 Webhook 服务器:在配置里声明 HTTP 端点,触发后执行本地命令。下面跑通最小链路,再接 GitHub 和 Slack 两个场景,覆盖 Webhook 配置、签名验证与传参给脚本;反向代理、systemd 部署不展开。
先跑通:一条 curl 触发本地脚本
先把最短的 hooks.json 存下来,内容只有一个 hook 对象:
[{ "id": "redeploy-webhook", "execute-command": "redeploy.sh", "command-working-directory": "/var/webhook" }]启动服务并发送一次 POST,redeploy.sh会被立即执行:
webhook -hooks hooks.json -verbose # 启动,默认监听 9000 端口 # 下面这条请求命中 /hooks/redeploy-webhook,脚本随之执行 curl -X POST http://localhost:9000/hooks/redeploy-webhook✅ 此刻你已有「请求进、命令出」的完整链路。接下来给它加上规则和参数。
Webhook 配置骨架:6 个字段速览
| 字段 | 作用 | 一句话说明 | 内联示例 |
|---|---|---|---|
id | 端点路径 | 决定 URL 是/hooks/<id> | "id": "redeploy-webhook" |
execute-command | 执行的命令 | 只放可执行文件路径,参数必须另配 | "execute-command": "redeploy.sh" |
command-working-directory | 脚本工作目录 | 同时决定相对命令的查找位置 | "command-working-directory": "/var/webhook" |
response-message | 回给调用方 | 命令完成后才返回的输出不走这里 | "response-message": "OK" |
pass-arguments-to-command | 传参给脚本 | 把请求值变成命令行参数 | {"source": "payload", "name": "ref"} |
trigger-rule | 触发条件 | 签名、token、IP 校验全在这 | "and": [ ... ] |
完整字段(含http-methods、include-command-output-in-response等)以 Hook 定义页为准,这里不逐字段展开。
GitHub Webhook 触发命令:怎么配、签名怎么验
场景:代码推到 master 时,自动在服务器跑部署脚本。
触发条件用and组合两条规则:先验签名,再限定分支。
"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" } } } ] }签名验证:GitHub 侧的 Secret token 必须与配置里的secret完全一致;请求头X-Hub-Signature的值带sha1=前缀,若用逗号传了多个签名,webhook 会逐个尝试直到匹配。
一个踩坑点:2.8 及以上版本签名类型写payload-hmac-sha1,老版本写payload-hash-sha1。写错类型不会报错,而是签名永远不匹配,表现为请求全部被拒。
Slack 斜杠命令:触发怎么配、token 怎么验
场景:在 Slack 频道里敲一条斜杠命令,后台跑你的脚本并立刻回执。
{ "id": "slack-command", "execute-command": "/scripts/slack-command.sh", "response-message": "已收到,后台执行中", "trigger-rule": { "match": { "type": "value", "value": "YOUR-TOKEN", "parameter": { "source": "payload", "name": "token" } } } }token 验证:Slack 配置斜杠命令时生成的 Token 本身就是凭证,直接做value匹配,不需要 HMAC。
一个踩坑点:Slack 要求 3 秒内收到响应。默认情况下 webhook 在后台执行命令并立即返回response-message,长任务因此不会超时;但回执文本只会在频道显示这一次,建议保持短句。
让数据流进来:Webhook 传参给脚本
取值语法:规则与pass-arguments-to-command共用同一套点号路径,数组按下标、XML 属性用-前缀、节点文本用#text。
| 想取的值 | name写法 | 备注 |
|---|---|---|
| 第一个提交的 id | commits.0.commit.id | 数组用数字下标 |
| 数组 payload 的第二项事件 | root.1.event | 数组体被包进root对象 |
| XML 的 user 属性 | app.users.user.0.-name | 属性加-,文本加#text |
| 整个请求体 | source用entire-payload | 原样交给脚本 |
文件传递:二进制放在 payload 里是 base64 字符串,直接当参数会撑爆 argv 长度,写成临时文件更稳;base64decode负责解码,脚本通过envname指定的环境变量拿到文件路径。
"pass-file-to-command": [ { "source": "payload", "name": "binary", "envname": "FILE_DATA", "base64decode": true } ]非 JSON 体:有些平台把 JSON 当字符串塞在普通字段里(如 Travis 的payload、multipart 的某个 part),点号取值会拿到整个字符串,必须先解析成对象。
"parse-parameters-as-json": [ { "source": "payload", "name": "payload" } ]⚠️必须配 trigger-rule:没有规则的 hook 等于「知道 URL 就能执行你的命令」。
- secret 不要硬编码:用
-template参数把密钥经模板注入,配置文件只留占位符 - 建议限定
http-methods:只放行POST,拦截 GET 探测 - 可选 IP 白名单:藏在反向代理后面时,
ip-whitelist验到的是代理 IP,必须改在代理层限制来源 - 命令用最小权限:靠
command-working-directory圈定活动范围,脚本以非 root 账号运行
调不通时先看这里
| 现象 | 最可能原因 | 一条验证命令 |
|---|---|---|
404Hook not found. | URL 的 id 与配置里的id不一致 | curl -i http://localhost:9000/hooks/<id> |
Hook rules were not satisfied. | secret/token 与平台侧不一致 | echo -n "$BODY" \| openssl dgst -sha1 -hmac "$SECRET"与请求头比对 |
| 命令没执行,返回 500 | execute-command路径不存在或无执行权限 | ls -l /var/webhook/redeploy.sh |
| 命令跑了但 payload 取值全空 | 请求没带Content-Type: application/json | curl -H "Content-Type: application/json" -X POST -d @body.json http://localhost:9000/hooks/<id> |
不想把密钥硬编码进配置文件,就上-template参数用 Go 模板注入,用法见 docs/Templates.md。再深的兼容问题,直接去项目 issue 区按trigger-rule搜,多数场景已有答案。
【免费下载链接】webhookwebhook is a lightweight incoming webhook server to run shell commands项目地址: https://gitcode.com/gh_mirrors/we/webhook
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考