OliveTin 3000.21.0 常用命令与运维实战(核心篇)

OliveTin 日常运维核心篇:生命周期与热重载、CLI 启动参数、API/Webhook 四种触发 curl 实测、8 条真实回显排障实录与单文件升级,基于 v3000.21.0 实机验证。

OliveTinOliveTin自托管运维自动化2026/10/28

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 found0
YAML 语法错误Configuration load failed: yaml: line 3: did not find expected '-' indicator1
字段拼写错误(如 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 三步)与版本回滚见部署篇第七节,两条路径的配置文件完全通用。

八、参考链接

  1. 官方 API 文档(25 端点与 OpenAPI 定义):https://docs.olivetin.app/api/intro.html
  2. 官方 OpenAPI 定义(3000.x,本文端点表来源):https://docs.olivetin.app/api/swagger/3k/OliveTin.openapi.json
  3. 官方 Webhook 文档:https://docs.olivetin.app/actions/executing-on-webhook.html
  4. 官方 CLI 安装与 systemd 文档:https://docs.olivetin.app/installation/targz.html
  5. 官方 releases(版本下载与 release notes,含 3000.21.0 新参数说明):https://github.com/OliveTin/OliveTin/releases
  6. 本专栏相关篇目:《OliveTin 3000.21.0 介绍与选型指南》、《OliveTin 3000.21.0 Docker Compose 部署实战》、《OliveTin 3000.21.0 配置参数详解》