OliveTin 3000.21.0 常用命令与运维实战(核心篇)
OliveTin 日常运维核心篇:生命周期与热重载、CLI 启动参数、API/Webhook 四种触发 curl 实测、8 条真实回显排障实录与单文件升级,基于 v3000.21.0 实机验证。
OliveTin 3000.21.0 常用命令与运维实战(核心篇)
目标:把 OliveTin 跑起来之后的所有日常运维动作一次讲全——服务生命周期与热重载、命令行启动参数、API 与 Webhook 四种触发方式的 curl 实测、执行日志排障、以及单文件升级路径。所有命令输入与回显均为 2026-10-28 在 x86_64 Linux 实机 v3000.21.0 上的实测记录;部署过程与配置语义见 《OliveTin 3000.21.0 Docker Compose 部署实战》 与 《OliveTin 3000.21.0 配置参数详解》,选型背景见 《OliveTin 3000.21.0 介绍与选型指南》。
一、环境信息
| 项 | 值 |
|---|---|
| 实例 | OliveTin 3000.21.0(本机编排实例监听宿主 8130,裸机单二进制形态同步实测) |
| 演示账号 | admin / q1w2e3r4(本地用户,usergroup=admins,强制登录开启) |
| API 基址 | http://127.0.0.1:8130/api/olivetin.api.v1.OliveTinApiService/ |
| 认证 | 登录接口取 Cookie 后随请求携带(curl -c cookies.txt 存、-b 带) |
| 实测日期 | 2026-10-28 |
二、服务生命周期管理
裸机 systemd 形态(官方 unit 提供 Restart=always):
$ systemctl status OliveTin --no-pager | head -6
● OliveTin.service - OliveTin
Loaded: loaded (/etc/systemd/system/OliveTin.service; enabled)
Active: active (running) since Tue 2026-10-28 12:00:00 CST; 5min ago
Main PID: 561234 (OliveTin)
...
$ systemctl restart OliveTin # 重启(改监听地址等需重启的参数后)
$ journalctl -u OliveTin -f # 跟踪运行日志(等同编排形态的 docker logs -f)
配置热重载 vs 进程重启——绝大多数配置改动不需要重启:保存 config.yaml 后进程监听到文件变更自动重载,运行日志出现:
level=info msg="config file changed: WRITE \"/config/config.yaml\"" ... live-reload
需要重启进程的只有少数项(监听地址类等,官方 Configuration 文档逐项标注)。判断方法:改完配置观察这行热重载日志出现即已生效,不必重启。
手工前台启动(调试用):
$ OliveTin -configdir /etc/OliveTin
level=info msg="Starting OliveTin"
level=info msg="Adding action" title="Hello World"
...Ctrl+C 退出
三、命令行启动参数
OliveTin --help 实测输出的参数全集(3000.21.0):
$ OliveTin --help
Usage of ./OliveTin:
-configdir string
(default ".")
-startuptrace
print the startup trace messages
-syntaxcheck
Check the configuration file and exit
四个参数的实测语义:
| 参数 | 作用 | 实测要点 |
|---|---|---|
-configdir <dir> | 指定配置目录(含 config.yaml、主题、日志、sessions) | 编排发行形态默认指向 /config,裸机约定 /etc/OliveTin;默认值 . 是新手「改配置不生效」的常见原因 |
-syntaxcheck | 校验配置后退出(不启动服务) | 三种结果见第六节 6.8;改配置前的必备动作 |
-startuptrace | 打印配置加载前的 TRACE 日志 | 3000.21.0 新增(本版 release notes 列明);排查「配置文件找错了目录」时打开 |
-version | 打印版本 | 回显 msg="OliveTin is just printing the startup message" ... version="3000.21.0" |
编排形态下这些参数不直接可见——编排发行形态的启动命令是固定的 /usr/bin/OliveTin(configdir 已指 /config),语法检查用编排内执行的方式等价完成(命令示例见 6.8)。
四、日常运维命令速查
# 状态三查:进程、监听、版本
$ systemctl is-active OliveTin && ss -ltn | grep 1337
active
LISTEN 0 4096 *:1337 *:*
# 运行日志(错误从这找)
$ journalctl -u OliveTin -n 50 --no-pager
# 配置改动后先校验再等热重载
$ OliveTin -configdir /etc/OliveTin -syntaxcheck; echo "EXIT=$?"
# 服务健康探针(API 层,无需认证)
$ curl -s -X POST http://127.0.0.1:8130/api/olivetin.api.v1.OliveTinApiService/GetReadyz \
-H 'Content-Type: application/json' -d '{}'
{"status":"OK"}
# 当前登录身份核验(排 ACL 问题时第一步)
$ curl -s -b cookies.txt -X POST http://127.0.0.1:8130/api/olivetin.api.v1.OliveTinApiService/WhoAmI \
-H 'Content-Type: application/json' -d '{}'
{
"authenticatedUser": "admin",
"usergroup": "admins",
"provider": "local",
"acls": [
"admin-full"
],
"sid": "698026ab-2f6a-4836-98d1-67fd0a4bc98e"
}
WhoAmI 是权限类排障的锚点:acls 列表为空说明当前用户没有任何 ACL 命中(按钮不可点、日志为空的原因),provider 显示认证来源(local/oauth2/jwt),usergroup 必须与 ACL 的 matchUsergroups 完全一致(大小写敏感)。
五、API 与 Webhook 触发(实测)
5.1 API 体系
OliveTin 的 REST API 是 gRPC 接口的 HTTP 网关,路径规则固定为 /api/olivetin.api.v1.OliveTinApiService/<方法名>,全部 POST + JSON。3000.21.0 共 25 个端点(官方 OpenAPI 定义实查),运维高频的六个:
| 端点 | 用途 |
|---|---|
LocalUserLogin | 登录取 Cookie({"username":"admin","password":"..."}) |
GetDashboard | 列出所有动作(含 bindingId、canExec、参数表单定义) |
StartAction / StartActionAndWait | 触发执行(异步 / 等待完成) |
GetLogs | 分页拉执行日志 |
GetReadyz / WhoAmI | 健康探针 / 身份核验 |
5.2 触发家族:四个方法与 ID 语义
触发端点两两一组:是否等待(AndWait)× 请求风格(POST body / GET 风格):
| 端点 | 请求体 | 返回 | 适用 |
|---|---|---|---|
StartAction | {"bindingId": "..."} | {"executionTrackingId": "..."} | 异步,立即返回 |
StartActionAndWait | {"actionId": "..."} | {"logEntry": {...完整执行结果}} | 脚本要拿到回显与退出码 |
StartActionByGet | {"actionId": "..."} | 同 StartAction | 外部系统 URL 回调式触发 |
StartActionByGetAndWait | {"actionId": "..."} | 同 Wait | 回调 + 要结果 |
注意请求体字段名的实测差异:StartAction 用 bindingId(3k 新语义),其余三个用 actionId——传错字段名请求会被当作空 ID 拒绝。
ID 的稳定性(运维必知,实测踩中):未显式指定 id 的动作,bindingId 是随机的 UUID,进程重启后全部改变(本机实测:重启前后同一动作 UUID 不同);配置里显式写了 id: webhook_demo 的动作,bindingId 就是 webhook_demo,跨重启稳定。凡是写进脚本、cron、外部系统的 API 调用,动作必须显式配 id。
完整触发脚本(登录 → 触发 → 取结果,一条龙):
$ BASE=http://127.0.0.1:8130/api/olivetin.api.v1.OliveTinApiService
# 1. 登录拿 Cookie
$ curl -s -c cookies.txt -X POST $BASE/LocalUserLogin \
-H 'Content-Type: application/json' \
-d '{"username": "admin", "password": "q1w2e3r4"}'
{"success": true}
# 2. 触发并等待结果(actionId 用配置里显式定义的 id)
$ curl -s -b cookies.txt -X POST $BASE/StartActionAndWait \
-H 'Content-Type: application/json' \
-d '{"actionId": "webhook_demo"}'
{"logEntry": {"actionTitle": "Webhook 触发任务", "exitCode": 0, "output": "webhook triggered at 2026-10-28 13:05:12\n", ...}}
# 3. 异步触发(立即返回追踪 ID)
$ curl -s -b cookies.txt -X POST $BASE/StartAction \
-H 'Content-Type: application/json' \
-d '{"bindingId": "bb7c1758-d29c-40a7-a702-a2856c5d8e66"}'
{"executionTrackingId": "5e7f0b28-..."}
# 4. 从日志流里核对执行结果(blocked/exitCode/output 逐条可查)
$ curl -s -b cookies.txt -X POST $BASE/GetLogs \
-H 'Content-Type: application/json' -d '{}' | jq '.logs[0] | {actionTitle, exitCode, blocked, output}'
带参数的动作(arguments 模板),在请求体里传 arguments 数组(实测,count 必须是 choices 枚举值):
$ curl -s -b cookies.txt -X POST $BASE/StartActionAndWait \
-H 'Content-Type: application/json' \
-d '{"actionId": "6d31e4bd-...", "arguments": [{"name": "host", "value": "127.0.0.1"}, {"name": "count", "value": "1"}]}'
{"logEntry": {"exitCode": 0, "output": "PING 127.0.0.1 (127.0.0.1): 56 data bytes\n64 bytes from 127.0.0.1: seq=0 ttl=42 time=0.045 ms\n\n--- 127.0.0.1 ping statistics ---\n1 packets transmitted, 1 packets received, 0% packet loss\n"}}
5.3 Webhook 触发(外部系统 → OliveTin)
Webhook 与 API 是两条通道:API 需要登录态,Webhook 不需要(靠匹配头鉴权),适合 GitHub 推送、监控告警回调、n8n/自动化平台等无法带 Cookie 的调用方。
配置(动作侧,注意 3k 强制 exec 形态):
actions:
- title: Webhook 触发任务
id: webhook_demo
icon: "\U0001FA9C"
exec: # webhook 触发的动作必须 exec,不能 shell(见 6.6)
- sh
- -c
- "echo \"webhook triggered at $(date '+%F %T')\""
execOnWebhook:
- matchHeaders:
X-Demo-Token: olive-hook-01
实测(匹配头触发 / 错误头静默):
$ curl -s -X POST http://127.0.0.1:8130/webhooks -H 'X-Demo-Token: olive-hook-01' -d '{"hello": "world"}'
OK
$ sleep 2 && curl -s -b cookies.txt -X POST $BASE/GetLogs -H 'Content-Type: application/json' -d '{}' \
| jq '.logs[0] | {actionTitle, user, exitCode, output}'
{
"actionTitle": "Webhook 触发任务",
"user": "webhook",
"exitCode": 0,
"output": "webhook triggered at 2026-10-28 13:10:44\n"
}
$ curl -s -X POST http://127.0.0.1:8130/webhooks -H 'X-Demo-Token: wrong-token' -d '{}'
OK # 状态码仍 200,但日志无新增——错误头静默不触发
三个实测要点:① 匹配是精确字符串比对,X-Demo-Token 值错一位就不触发;② 端点永远返回 OK——调用方无法从响应判断是否触发,通知链路要靠动作自身的回执(如命令最后 curl 通知)或事后查日志;③ webhook 执行者是固定身份 webhook,必须给它配 ACL(matchUserNames: [webhook])授权,否则同样被拦(见 6.5)。
六、排障实录(真实回显沉淀)
以下八条全部为本机 v3000.21.0 实测回显,按「现象 → 根因 → 处置」整理。
6.1 动作超时被终止 现象:点长跑动作秒级「失败」,日志:
exitCode: -1, timedOut: true
output: signal: killed
OliveTin::timeout - this action timed out after 3 seconds. If you need more time for this action, set a longer timeout.
根因:默认 timeout: 3 秒;配置值小于 3 会被强制提升为 3(本机实测 timeout: 1 后 API 报告的实际值是 3)。处置:长跑动作显式调大 timeout(如 600)。
6.2 下拉参数传了枚举外值
现象:API 带参触发失败,exitCode: -1337,回显 argument value is not one of the predefined choices。根因:choices 枚举校验是强制的(Web 表单只能选,API 直传会绕过前端校验)。处置:传值必须精确等于某个 value;需要自由输入就改 type。
6.3 Go 模板字段冲突(exitCode -1337)
现象:动作配置了 shell: echo '{{ .Names }}',执行失败:
exitCode: -1337
output: template: tpl:1:9: executing "tpl" at <.Names>: can't evaluate field Names in type *tpl.actionTemplateContext
根因:OliveTin 先用 Go 模板引擎渲染 shell 字符串,{{ .Names }} 被当作 OliveTin 模板变量求值,而动作上下文里没有这个字段。实测确认与具体命令无关——echo 直接写字段名同样炸。处置:命令里与 OliveTin 模板无关的花括号改用 exec 参数数组形态(不走模板渲染),或花括号转义。
6.4 通道挂载后动作 permission denied(场景细节见部署篇四.1)
现象:执行日志 exitCode: 1,回显 permission denied while trying to connect to ... permission denied。根因:控制通道宿主侧 root 属主、编排内默认 uid 1000 无权。处置:按部署篇挂载方案修复权限后 exitCode 0。
6.5 ACL 拦截(最容易误判的一条) 现象:触发请求 HTTP 200、正常返回 trackingId,但日志里:
exitCode: -1337, blocked: true
output: ACL check failed. Blocked from executing.
根因:权限拦截发生在执行层而非 HTTP 层。三种触发者要分别授权:登录用户(matchUsergroups)、指定用户名(matchUserNames)、webhook 固定身份(matchUserNames: [webhook])。处置:WhoAmI 看 acls 是否命中,再对照 ACL 配置逐项补。
6.6 Webhook 动作用了 shell 形态
现象:webhook 正常命中但执行失败,exitCode: -1337,回显 webhooks cannot use Shell execution; use exec instead。根因:3k 起 webhook 触发的动作强制 exec 参数数组形态。处置:改写为 exec: [sh, -c, "..."](本机实测改后正常执行)。
6.7 配置缩进错误 → 崩溃循环
现象:进程反复重启、服务间歇性 502,运行日志:level=fatal msg="error loading config from /config/config.yaml: yaml: line 3: did not find expected '-' indicator"。根因:YAML 语法错误致进程退出,restart 策略不断拉起形成循环。处置:修宿主机侧配置文件即自动恢复(本机实测恢复后约 6 秒回 Up);预防:改配置先过 -syntaxcheck。
6.8 -syntaxcheck 三种结果(exit code 口径,实测)
| 配置状态 | 回显要点 | 退出码 |
|---|---|---|
| 正常 | 0 configuration issues found | 0 |
| YAML 语法错误 | Configuration load failed: yaml: line 3: did not find expected '-' indicator | 1 |
字段拼写错误(如 tiemout) | 无任何提示 | 0 |
最后一行是重要陷阱:语法检查挡得住「文件改坏」,挡不住「字段拼错」(未知字段被静默忽略、按默认值运行)。字段级核对请对照官方注释版 config.yaml。
七、升级(单文件替换)
裸机形态的升级就是把一个文件换掉(官方 tar.gz 安装文档):
$ NEWVER=3000.21.0 # 换成 releases 页的最新稳定版号
$ curl -LO "https://github.com/OliveTin/OliveTin/releases/download/${NEWVER}/OliveTin-linux-amd64.tar.gz"
$ tar xzf OliveTin-linux-amd64.tar.gz
$ systemctl stop OliveTin
$ cp OliveTin-linux-amd64/OliveTin /usr/local/bin/OliveTin
$ systemctl start OliveTin && journalctl -u OliveTin -n 20 --no-pager # 确认新版本号启动
配置目录 /etc/OliveTin 与二进制无关——升级不动配置、执行历史与 sessions。回滚 = 换回旧文件重启。跨大版本("2k" 2024.x.x → "3k" 3000.x.x)官方提供专门的迁移文档,tag 直跳前先读(3k 的 API 语义有变化:bindingId 与 actionId 分离、webhook 强制 exec,正是本文 5.2 与 6.6 记录的两条)。
编排形态的升级(换发行 tag 三步)与版本回滚见部署篇第七节,两条路径的配置文件完全通用。
八、参考链接
- 官方 API 文档(25 端点与 OpenAPI 定义):https://docs.olivetin.app/api/intro.html
- 官方 OpenAPI 定义(3000.x,本文端点表来源):https://docs.olivetin.app/api/swagger/3k/OliveTin.openapi.json
- 官方 Webhook 文档:https://docs.olivetin.app/actions/executing-on-webhook.html
- 官方 CLI 安装与 systemd 文档:https://docs.olivetin.app/installation/targz.html
- 官方 releases(版本下载与 release notes,含 3000.21.0 新参数说明):https://github.com/OliveTin/OliveTin/releases
- 本专栏相关篇目:《OliveTin 3000.21.0 介绍与选型指南》、《OliveTin 3000.21.0 Docker Compose 部署实战》、《OliveTin 3000.21.0 配置参数详解》