Kimai 2.71 常用命令与运维实战
本文逐条实测 Kimai 2.71.0 的命令行工具链与 JSON API:19 条 `kimai:` 命令全家桶(用户管理、安装升级、缓存重载、发票、导出、邮件、插件)、API 令牌创建与 Bearer 认证、核心端点(客户/项目/活动/时间表/费率)的 CRUD 全流程、备份恢复,以及 6 个真实排障案例(含 2.71.0 移除 API 密码后的认证迁移与 `X-AUTH-TOKEN` 失效问题)。配置体系见 [《Kimai 2.71 配置参数详解》](https://www.quzuo.net/document/rUgrmnGbREdD),部署过程见 [《Kimai 2.71 Docker Compose 部署实战》](https://www.quzuo.net/document/3CNq42eP7Z4D)。
Kimai 2.71 常用命令与运维实战
本文逐条实测 Kimai 2.71.0 的命令行工具链与 JSON API:19 条
kimai:命令全家桶(用户管理、安装升级、缓存重载、发票、导出、邮件、插件)、API 令牌创建与 Bearer 认证、核心端点(客户/项目/活动/时间表/费率)的 CRUD 全流程、备份恢复,以及 6 个真实排障案例(含 2.71.0 移除 API 密码后的认证迁移与X-AUTH-TOKEN失效问题)。配置体系见 《Kimai 2.71 配置参数详解》,部署过程见 《Kimai 2.71 Docker Compose 部署实战》。
一、命令行工具总览
1.1 入口与执行环境
Kimai 的命令行入口是 Symfony Console:安装目录下的 bin/console。裸机部署直接在安装目录执行;官方镜像部署则在应用侧进入安装目录 /opt/kimai/ 执行(部署篇的编排下等价写法为 docker compose exec kimai bin/console <命令>)。本文所有命令均在 /opt/kimai/ 目录下以 bin/console <命令> 形式实测,输出为真实回显。
1.2 kimai 命令命名空间全景
bin/console list kimai
实测回显(2.71.0 共 19 条专用命令):
Available commands for the "kimai" namespace:
kimai:export:create Create exports
kimai:install [kimai:update] Install and update Kimai
kimai:invoice:create Create invoices
kimai:mail:test Send a test email using MAILER_URL and MAILER_FROM
kimai:plugins Manage Kimai plugins
kimai:reload Reload Kimai caches
kimai:reset:dev Resets the "development" environment
kimai:reset:locales Regenerate the locale definition file
kimai:reset:test Resets the "test" environment
kimai:timesheet:stop-all Stop all running timesheets immediately
kimai:translations Automated translation adjustments
kimai:update Install and update Kimai
kimai:user:activate Activate a user
kimai:user:create Create a new user
kimai:user:deactivate Deactivate a user
kimai:user:demote Demote a user by removing a role
kimai:user:list List all users
kimai:user:password Change the password of a user
kimai:user:promote Promotes a user by adding a role
kimai:version Show version information
除 kimai: 专用命令外,底层 Symfony 与 Doctrine 的通用命令在运维中同样高频:about(环境信息)、cache:clear(缓存)、doctrine:migrations:status(迁移状态)、dbal:run-sql(直连执行 SQL)、debug:config(查看生效配置)、debug:dotenv(查看环境变量)、debug:router(路由表)。命令按需选择:日常管理集中在二、三节,发票导出在四节,维护在五节,API 集成在六节。
二、版本、安装与缓存命令
2.1 kimai:version
bin/console kimai:version
实测回显:
Kimai 2.71.0 by Kevin Papst.
2.2 about:运行环境一屏总览
bin/console about
实测回显(节选,完整输出含 Kernel/PHP/Environment 三大段):
-------------------- ---------------------------------
Symfony
-------------------- ---------------------------------
Version 6.4.48
Long-Term Support Yes
End of maintenance 11/2026 (in +34 days)
End of life 11/2027 (in +399 days)
-------------------- ---------------------------------
PHP
Version 8.3.36
Architecture 64 bits
Timezone UTC (2026-10-27T15:29:19+00:00)
OPcache true
APCu false
Xdebug false
排障价值:确认实际运行的 PHP 版本(官方要求 8.2–8.5,本环境 8.3.36)、OPcache 是否启用、Symfony 版本是否为 6.4 LTS。
2.3 kimai:install / kimai:update(幂等)
kimai:install 与 kimai:update 互为别名(同一命令),负责建库、执行 Doctrine 迁移、重建缓存。在已安装环境重跑(-n 免交互):
bin/console kimai:install -n
实测回显(已略去 deprecation 日志行):
[OK] Cache for the "prod" environment (debug=false) was successfully cleared.
// Warming up the cache for the prod environment with debug false
[OK] Cache for the "prod" environment (debug=false) was successfully warmed.
[OK] Successfully installed Kimai version 2.71.0 🎉
结论:安装与升级是同一条幂等命令——重复执行安全无害(迁移链已到头则跳过),这正是部署篇重启时序中每次启动都重跑它的原因。配合迁移状态查询:
bin/console doctrine:migrations:status | head -6
实测回显:
+----------------------+----------------------------------------+
| Configuration |
+----------------------+----------------------------------------+
| Storage | Doctrine\\Migrations\\Metadata\\Storage\\TableMetadataStorage
| Current Version | 2026-10-25 12:00:00 (DoctrineMigrations\\Version20261025120000)
| Previous Version | 2026-10-19 16:27:27 (DoctrineMigrations\\Version20261019162727)
2.4 kimai:reload(改配置后必跑)
bin/console kimai:reload
实测回显:
// Warming up the cache for the prod environment with debug false
[OK] Cache for the "prod" environment (debug=false) was successfully warmed.
[OK] Kimai config was reloaded
与裸 cache:clear 的区别:kimai:reload 在清缓存之余同步重建翻译/locale 与应用配置缓存,是配置篇 3.2 节覆盖机制的生效步骤。它不需要 cache:clear 配合,单独一次即可。
2.5 kimai:reset:locales / kimai:translations
bin/console kimai:reset:locales
实测回显(重新生成 locale 定义文件,节选尾部):
* HH 'h' mm
输出为逐条 locale 规则的再生过程,无 [OK] 结束语属正常。kimai:translations 用于开发态翻译整理,kimai:reset:dev/kimai:reset:test 仅重置开发/测试环境(生产环境执行无害但无意义)。
三、用户管理命令
3.1 kimai:user:list
bin/console kimai:user:list
实测回显(当前环境已建两个用户):
---------- ------------------- ----------------------------- -------- ---------------
Username Email Roles Active Authenticator
---------- ------------------- ----------------------------- -------- ---------------
admin admin@example.com ROLE_SUPER_ADMIN, ROLE_USER Yes kimai
kevin kevin@example.com ROLE_TEAMLEAD, ROLE_USER Yes kimai
---------- ------------------- ----------------------------- -------- ---------------
Authenticator 列显示账号的认证来源:kimai(内部口令)/ldap/saml——排查「能否用命令重置密码」时先看这列(外部认证账号改本地密码无意义)。
3.2 kimai:user:create
bin/console kimai:user:create <username> <email> [<role>] [<password>]
实测(创建普通用户并回查):
bin/console kimai:user:create kevin kevin@example.com ROLE_USER q1w2e3r4
[OK] Success! Created user: kevin
重复创建的报错回显(用户名唯一性约束):
bin/console kimai:user:create admin admin2@example.com ROLE_USER q1w2e3r4
[ERROR] username: The username is already used.
参数要点:role 支持逗号分隔多角色(如 ROLE_USER,ROLE_ADMIN);省略 password 时交互式询问;--request-password 强制用户首登改密;--ignore-existing 让幂等脚本化建号在用户已存在时退出码为 0(Ansible 类工具友好)。
3.3 角色升降与密码:promote / demote / password
bin/console kimai:user:promote kevin ROLE_TEAMLEAD
[OK] Role "ROLE_TEAMLEAD" has been added to user "kevin".
bin/console kimai:user:demote kevin ROLE_TEAMLEAD
bin/console kimai:user:password kevin q1w2e3r4
[OK] Role "ROLE_TEAMLEAD" has been removed from user "kevin".
[OK] Changed password for user "kevin".
角色语义与权限矩阵的对应关系见配置篇 6.1 节(maps 段)。
3.4 停用与恢复:deactivate / activate
bin/console kimai:user:deactivate kevin
bin/console kimai:user:activate kevin
[OK] User "kevin" has been deactivated.
[OK] User "kevin" has been activated.
停用只是禁登录,数据保留;kimai:user:list 的 Active 列相应翻转。注意 2.71.0 没有 user:delete 命令——这是刻意设计(时间记录的外键完整性),离职人员一律停用而非删除。
四、发票与导出命令
4.1 kimai:invoice:create:命令行开发票
bin/console kimai:invoice:create --help
实测回显(参数全集):
Description:
Create invoices
Usage:
kimai:invoice:create [options]
Options:
--user=USER The user to be used for generating the invoices
--start[=START] Start date (format: 2020-01-01, default: start of the month)
--end[=END] End date (format: 2020-01-31, default: end of the month)
--timezone[=TIMEZONE] Timezone for start and end date query (fallback: users timezone)
--customer[=CUSTOMER] Comma separated list of customer IDs
--project[=PROJECT] Comma separated list of project IDs
--by-customer If set, one invoice for each active customer in the given timerange is created
--by-project If set, one invoice for each active project in the given timerange is created
--set-exported [DEPRECATED] this flag has no meaning any more: invoiced items are always exported
--template[=TEMPLATE] Invoice template
--search[=SEARCH] Search term to filter invoice entries
--exported[=EXPORTED] Exported filter for invoice entries (possible values: exported, all), by default only "not exported" items are fetched
--preview[=PREVIEW] Absolute path for a rendered preview of the invoice, which will neither be saved nor the items be marked as exported.
--preview-unique Adds a unique part to the filename of the generated invoice preview file, so there is no chance that they get overwritten on same project name.
成功实测(客户 2 本月已有两条未开票记录,小时费率与固定费率各一条):
bin/console kimai:invoice:create --user admin --customer 2 --template '标准服务发票'
回显(伴随 3 条 twig 弃用 INFO 日志,见 8.6 节):
+----+---------------+----------+---- Created 1 invoice(s) -------------------------------------+
| ID | Customer | Total | Filename |
+----+---------------+----------+---------------------------------------------------------------+
| 2 | Beta 咨询公司 | 1725 CNY | /opt/kimai/var/data/invoices/2026-002-Beta_zi_xun_gong_si.pdf |
+----+---------------+----------+---------------------------------------------------------------+
金额 1725 = 525(1.5h × 350 小时费率)+ 1200(固定费率),与 API 侧费率计算精确一致;PDF 落盘 /opt/kimai/var/data/invoices/(部署篇 6.2 节的备份目录)。开票条目随即被标记 exported=1(--set-exported 因成默认而弃用)——这是理解 8.3 节排障的前提。
4.2 kimai:export:create:时间表导出
bin/console kimai:export:create --username admin --start 2026-10-01 --end 2026-10-31 --customer 2 --template 'csv'
[OK] Saved export to: /tmp/20261027-Beta_zi_xun_gong_si.csv
导出内容实测(首部数据行,列头与数据对应):
Date,From,To,Duration,Currency,Price,"Internal price","Hourly price","Fixed price",Name,User,E-mail,"Staff number",Customer,Project,Activity,Description,Billable,Tags,Type,category,Account,"Project number",VAT-ID,"Order number"
2026-10-27,16:00,17:00,1:00,CNY,350,280,350,0,admin,admin,admin@example.com,,"Beta 咨询公司","移动端 App 开发",需求梳理,导出实测记录,1,,timesheet,work,0003,0003,,
两个必须注意的点:
-
--template必填。漏掉时的报错:[ERROR] You must pass the "template" option -
产物落在系统
/tmp(非var/data)——命令行导出是一次性交付物,执行后应立即取走;对运行中实例内的文件而言它随服务重建而消失。需要长期归档请走 Web 端导出或自行拷贝。
--username 决定导出用的权限与十进制设置;--set-exported 可在导出同时把条目标记为已导出(配合审计口径)。
五、维护命令
5.1 kimai:timesheet:stop-all
bin/console kimai:timesheet:stop-all
[OK] Stopped 0 timesheet records.
用途:停机维护/大量补录前的状态收敛(把所有用户运行中的计时一键停止)。数字为实际停止条数,当前环境无运行中记录故为 0。
5.2 kimai:mail:test
bin/console kimai:mail:test admin@example.com
echo "exit=$?"
实测回显(默认空传输器下静默成功):
exit=0
「成功」只代表走完邮件管道;真实 SMTP 验证语义见配置篇 8.2 节。
5.3 kimai:plugins
bin/console kimai:plugins
[WARNING] No plugins installed
插件管理入口:装好的插件经 var/plugins 目录持久化(部署篇编排已挂卷),升级 Kimai 后插件缓存同样由 kimai:reload 重建。官方商店插件(费用/任务管理/电子发票等)为付费 Bundle,安装方式为下载解压到 var/plugins/ 后执行 kimai:reload。
六、JSON API 实战
6.1 认证:创建访问令牌与 Bearer 头
2.71.0 的 API 认证流程(旧版「API 密码」特性已在 2.71.0 移除):
- Web 界面以目标用户登录,进入「个人配置 → API」页(路由
/profile/<用户名>/api-token); - 「Create」表单填令牌名称(可选有效期)提交;
- 创建结果页展示一次明文令牌(24 位十六进制),此后仅显掩码(页面参数
hide-token=1),令牌落库于kimai2_access_token表(明文存储,可追溯last_usage)。
请求时使用 Authorization: Bearer <令牌> 头。最小验证:
curl -s -H "Authorization: Bearer 0b57c60f251f97fdf38ec141c" http://127.0.0.1:8136/api/ping
{"message":"pong"}
API 端点面(bin/console debug:router | grep /api/ 实测统计):100 条路由 = 36 GET + 22 POST + 19 PATCH + 23 DELETE,读写全覆盖。Swagger 文档在 http://<主机>:8136/api/doc。
6.2 只读端点:version / users / customers / config
TOK='0b57c60f251f97fdf38ec141c'
curl -s -H "Authorization: Bearer $TOK" http://127.0.0.1:8136/api/version
{"version":"2.71.0","versionId":27100,"copyright":"Kimai 2.71.0 by Kevin Papst."}
curl -s -H "Authorization: Bearer $TOK" http://127.0.0.1:8136/api/users
[{"apiToken":false,"locale":"zh_CN","timezone":"Asia/Shanghai","language":"zh_CN","initials":"AD","color-safe":"#E91E63","id":1,"alias":null,"title":null,"avatar":null,"username":"admin","email":"admin@example.com","accountNumber":null,"enabled":true,"systemAccount":false,"color":null},{"apiToken":false,"locale":"en","timezone":"UTC","language":"en","initials":"KE","color-safe":"#0074D9","id":2,"username":"kevin","email":"kevin@example.com",...}]
curl -s -H "Authorization: Bearer $TOK" http://127.0.0.1:8136/api/config/timesheet
{"trackingMode":"default","defaultBeginTime":"now","activeEntriesHardLimit":1,"isAllowFutureTimes":true,"isAllowOverlapping":true}
时间跟踪配置经 API 只读暴露(trackingMode/hardLimit 与配置篇 4 节 YAML 值一一对应),便于外部系统探测实例行为。同族端点还有 /api/config/colors(28 色板)、/api/tags、/api/teams。
6.3 写入端点:客户 → 项目 → 活动三层创建
三层结构存在客户→项目的外键依赖,必须按序创建:
# 1. 建客户
curl -s -X POST -H "Authorization: Bearer $TOK" -H 'Content-Type: application/json' \
-d '{"name":"Beta 咨询公司","country":"CN","currency":"CNY","timezone":"Asia/Shanghai","comment":"文档实测创建"}' \
http://127.0.0.1:8136/api/customers
{"color-safe":"#a972c9","id":2,"name":"Beta 咨询公司","number":"0003",...,"currency":"CNY","timezone":"Asia/Shanghai",...}
# 2. 建项目(customer 指向客户 id,金额预算直接给数值)
curl -s -X POST -H "Authorization: Bearer $TOK" -H 'Content-Type: application/json' \
-d '{"name":"移动端 App 开发","customer":2,"budget":50000,"timeBudget":100000}' \
http://127.0.0.1:8136/api/projects
{"parentTitle":"Beta 咨询公司","customer":2,"id":2,"name":"移动端 App 开发","number":"0003","budget":50000.0,"timeBudget":360000000,...}
⚠️ 注意
timeBudget请求与回显的单位差异:本例请求传timeBudget: 100000(按小时口径),回显为360000000——即 100000 小时 × 3600 = 3.6 亿秒,API 存储/回显单位是秒而请求口径按小时折算。集成前先用一笔已知值核对单位语义(不同版本端点对单位处理存在差异),避免预算口径事故。
# 3. 建活动(project 指向项目 id)
curl -s -X POST -H "Authorization: Bearer $TOK" -H 'Content-Type: application/json' \
-d '{"name":"需求梳理","project":2}' http://127.0.0.1:8136/api/activities
{"parentTitle":"移动端 App 开发","project":2,"id":2,"name":"需求梳理","number":"0003",...}
6.4 时间表端点:开始 / 查询 / 停止
# 开始计时(不传时间 = 从现在开始)
curl -s -X POST -H "Authorization: Bearer $TOK" -H 'Content-Type: application/json' \
-d '{"project":2,"activity":2,"description":"D1 文档 API 实测计时"}' \
http://127.0.0.1:8136/api/timesheets
{"activity":2,"project":2,"user":1,"tags":[],"id":2,"begin":"2026-10-27T23:22:00+0800","end":null,"duration":0,"break":0,"description":"D1 文档 API 实测计时","rate":0.0,"internalRate":0.0,"fixedRate":null,"hourlyRate":null,"exported":false,"billable":true,"metaFields":[]}
# 运行中记录查询(含嵌套的客户/项目/活动对象)
curl -s -H "Authorization: Bearer $TOK" http://127.0.0.1:8136/api/timesheets/active | head -c 300
[{"tags":[],"id":2,"begin":"2026-10-27T23:22:00+0800","end":null,"duration":0,...,"description":"D1 文档 API 实测计时",...}]
# 停止计时——PATCH 方法(不是 POST,见 8.2 排障)
curl -s -X PATCH -H "Authorization: Bearer $TOK" http://127.0.0.1:8136/api/timesheets/2/stop
{"id":2,"begin":"2026-10-27T23:22:00+0800","end":"2026-10-27T23:23:00+0800","duration":60,...,"rate":0.0,"hourlyRate":0.0,...}
补录形态(起止时间显式给出)与固定费率:
curl -s -X POST -H "Authorization: Bearer $TOK" -H 'Content-Type: application/json' \
-d '{"project":2,"activity":2,"begin":"2026-10-27T10:00:00","end":"2026-10-27T12:30:00","fixedRate":1200,"description":"固定费率实测"}' \
http://127.0.0.1:8136/api/timesheets
{"id":3,"begin":"2026-10-27T10:00:00+0800","end":"2026-10-27T12:30:00+0800","duration":9000,"rate":1200.0,"fixedRate":1200.0,...}
集合查询(列表响应为精简序列化,无 fixedRate/hourlyRate 字段,消费脚本别按详情响应的字段集解析):
curl -s -H "Authorization: Bearer $TOK" 'http://127.0.0.1:8136/api/timesheets?size=10'
id=2 2026-10-27T23:22:00+0800 -> 2026-10-27T23:23:00+0800 dur=60s rate=0.0 desc=D1 文档 API 实测计时
id=1 2026-10-27T09:00:00+0000 -> 2026-10-27T11:42:00+0000 dur=9720s rate=0.0 desc=首页视觉稿迭代
id=4 2026-10-27T14:00:00+0800 -> 2026-10-27T15:30:00+0800 dur=5400s rate=525.0 desc=活动费率验证
id=3 2026-10-27T10:00:00+0800 -> 2026-10-27T12:30:00+0800 dur=9000s rate=1200.0 desc=固定费率实测
6.5 费率子资源
# 活动级小时费率(isFixed=false)/ 固定费率传 "fixed": true
curl -s -X POST -H "Authorization: Bearer $TOK" -H 'Content-Type: application/json' \
-d '{"rate":350,"internalRate":280}' http://127.0.0.1:8136/api/activities/2/rates
{"id":1,"user":null,"rate":350.0,"internalRate":280.0,"isFixed":false}
后续记录的折算联动(1.5h × 350 = 525;内部 1.5 × 280 = 420):
{"id":4,"duration":5400,"rate":525.0,"internalRate":420.0,"hourlyRate":350.0,...}
同族子资源:/api/projects/{id}/rates、/api/customers/{id}/rates(客户级兜底费率);读端点 GET .../rates、删端点 DELETE .../rates/{rateId}。三级费率优先级见配置篇 5.1 节。
七、备份与恢复
7.1 备份集 = 数据库 + var/data + var/plugins
# 数据库全量(业务数据全在这里)
mysqldump -ukimaiuser -p'q1w2e3r4' --single-transaction kimai | gzip > /opt/backup/kimai-$(date +%F).sql.gz
# 文件资产(发票 PDF、上传模板、logo、插件)
tar -czf /opt/backup/kimai-files-$(date +%F).tgz -C /opt/kimai var/data var/plugins
实测(库 35 张表,压缩产物 9227 字节):
-rw-r--r-- 1 root root 9227 Oct 27 23:25 /opt/backup/kimai-2026-10-27.sql.gz
--single-transaction 保证 InnoDB 一致性快照不锁表。MySQL 数据目录整拷(部署篇 bind mount 目录)只作应急手段,跨大版本不保证兼容,以逻辑 dump 为准。
7.2 恢复流程
- 按部署篇起一个空库实例(库名/用户名与备份一致);
gunzip -c kimai-2026-10-27.sql.gz | mysql -ukimaiuser -p kimai;- 解开
var/data、var/plugins到安装目录对应位置; - 启动应用——启动时序自动重跑
kimai:install,迁移链已到头则直接进入服务状态(部署篇 3.3 节日志可对照)。
八、排障实录
8.1 案例:老文档的 X-AUTH-TOKEN 头返回 401
现象:按 2.x 早期文档用 X-AUTH-TOKEN: <令牌> 调 API:
curl -s -H "X-AUTH-TOKEN: 0b57c60f251f97fdf38ec141c" http://127.0.0.1:8136/api/ping
{"code":401,"message":"Unauthorized"}
根因:2.71.0 移除了 API 密码特性,旧头随之失效;有效的认证头是 Authorization: Bearer。
对照实测:
$ curl -s -H "Authorization: Bearer 0b57c60f251f97fdf38ec141c" http://127.0.0.1:8136/api/ping
{"message":"pong"}
处置:所有集成改用 Authorization: Bearer;Basic Auth(-u 用户:密码)同样被拒(401)——用户名口令不是 API 凭据,必须经访问令牌。
8.2 案例:停止计时返回 405 Method Not Allowed
现象:按 REST 直觉用 POST /api/timesheets/{id}/stop:
{"code":405,"message":"Method Not Allowed"}
根因:该端点路由注册为 PATCH(stop_timesheet PATCH /api/timesheets/{id}/stop,debug:router 可查)。
处置:改用 curl -X PATCH 后正常返回停止后的记录详情(6.4 节回显)。同族 restart 端点同为 PATCH。规律:Kimai API 的「状态迁移类」操作(stop/restart)用 PATCH,资源创建用 POST——集成前用 debug:router 或 Swagger 核对方法。
8.3 案例:发票命令报 No invoice was generated
现象:
bin/console kimai:invoice:create --user admin --customer 1 --template '标准服务发票'
[WARNING] No invoice was generated
根因:发票只捞取**本月未导出(exported=0)**的条目;客户 1 本月唯一一条记录已在先前开票时被标记 exported=1(4.1 节机制),本月无未开票条目。数据库侧核对:
SELECT id,exported FROM kimai2_timesheet;
id exported
1 1
2 0
3 0
4 0
处置:换目标客户(customer 2 有未导出条目)立即成功(4.1 节回显);或按 --exported=all 重新开票全量条目(重复开票场景需自行控制业务语义)。同样机制下,kimai:export:create 报 No entries found, skipping 亦是「条目已被发票锁定」。
8.4 案例:导出产物落在 /tmp 且随服务重建消失
现象:kimai:export:create 成功后找不到文件。
根因:CLI 导出路径是系统临时目录(8.1 节实测 /tmp/20261027-Beta_zi_xun_gong_si.csv),不在 var/data 持久化范围。
处置:命令执行后立即取走文件;需要持久化交付物走 Web 导出界面(落 var/data)或脚本自行搬运。
8.5 案例:API 客户端解析列表响应报 KeyError
现象:按「详情响应」的字段集解析 /api/timesheets 列表,取 fixedRate 抛 KeyError。
根因:集合端点(列表)与单项端点(详情)的序列化深度不同——列表为精简形态(无 fixedRate/hourlyRate/user 嵌套等),详情才全量(6.4 节两种回显对照可见)。
处置:消费脚本按端点分别建模;需要完整字段时对列表里的 id 逐个取详情,或直接用 /api/timesheets?size=N 的分页参数控制批量。
8.6 案例:发票命令刷屏 deprecation 日志
现象:kimai:invoice:create/kimai:install 输出前滚出多条 deprecation.INFO: User Deprecated: Since twig/twig 3.29... JSON 日志。
根因:2.71.0 依赖树中 Symfony/Twig 上游的弃用提示(经 monolog 以 INFO 级打印),不影响功能结果——发票正常生成、安装正常完成。
处置:过滤 grep -v deprecation 查看有效输出;日志治理见 monolog 配置(config/packages/monolog.yaml),不必升级行为变更也不应作为报错处理。
8.7 排障速查表
| 现象 | 关键回显 | 定位 | 处置 |
|---|---|---|---|
| API 401 | {"code":401,"message":"Unauthorized"} | 头不对/令牌无效/令牌过期 | 改 Authorization: Bearer;Web 端重建令牌 |
| API 405 | {"code":405,"message":"Method Not Allowed"} | stop/restart 用了 POST | 改 PATCH |
| API 404 | {"code":404,"message":"Not Found"} | 端点不存在(如 /api/config 根路径) | debug:router 核对路由名 |
| 发票空生成 | No invoice was generated | 条目已 exported | 换客户/时段或 --exported=all |
| 导出报错 | You must pass the "template" option | 漏 --template | 补模板名 |
| 改密无效 | Authenticator 列非 kimai | LDAP/SAML 账号 | 到上游身份源改密 |
| 升级后异常 | 迁移版本落后 | 未跑安装命令 | kimai:install -n |
专栏四篇至此构成完整闭环:认知选型(《Kimai 2.71 介绍与选型指南》)→ 部署(《Kimai 2.71 Docker Compose 部署实战》)→ 配置(《Kimai 2.71 配置参数详解》)→ 本篇命令与运维。