ZenTao 22.6 常用 CLI 命令与运维实战
ZenTao 22.6 常用 CLI 命令与运维实战:ztcli 命令行入口、init 维护脚本、命令行备份恢复、计划任务运维与 API v1 调用实录
ZenTao 22.6 常用 CLI 命令与运维实战
版本基线:ZenTao 开源版 22.6(官方 Docker 形态,内置 MariaDB 10.6) 实测环境:按《ZenTao Docker Compose 部署实战》完成部署的 22.6 实例,应用根目录
/apps/zentao,内置 PHP/opt/zbox/bin/php约定:以下命令与回显均为实测记录;管理员账号admin / Q1w2e3r4
一、命令行工具面总览
禅道的命令行能力集中在应用根目录 bin/ 下,22.6 实测清单:
| 文件 | 用途 |
|---|---|
bin/ztcli | 命令行访问入口(CLI Router),可直接调用任意模块方法 |
bin/init.sh | 官方初始化脚本:生成全套维护 shell 脚本(交互式) |
bin/php/init.php | init.sh 的实际执行体,生成 cron 包装脚本与 sys.cron |
bin/php/crond.php | 计划任务守护程序(读取 bin/cron 目录按秒级轮询执行) |
bin/php/cleancache.php | 清理模板/数据缓存 |
bin/php/*.php | 其余辅助:checkyaml、encrypt、genapi 等 |
bin/*.sh(init.php 生成) | backupbackup.sh、mailasyncsend.sh 等单任务包装脚本 |
bin/cron/sys.cron | crontab 风格的系统定时任务清单(init.php 生成) |
bin/ztcli.sh / bin/cron.sh | init.php 生成的 ztcli 与 crond 包装 |
进入运行环境的标准方式(容器形态):
$ docker exec -it zentao-22.6-app bash
root@zentao-22.6-app:/apps/zentao#
二、ztcli:命令行访问入口
ztcli 是禅道官方的 CLI 路由入口(原理:定义 IN_SHELL 后加载框架 router,把 URL 参数解析成模块方法调用)。用法:
Usage: ztcli <request>
请求以完整 URL 形式给出,等价于浏览器访问该 URL。实测执行一次计划任务扫描:
$ /opt/zbox/bin/php /apps/zentao/bin/ztcli 'http://127.0.0.1:8143/index.php?m=cron&f=run'
(无输出,退出码 0;到期任务已被触发执行)
再如手工触发一次产品统计刷新:
$ /opt/zbox/bin/php /apps/zentao/bin/ztcli 'http://127.0.0.1:8143/index.php?m=product&f=refreshStats'
使用建议:ztcli 输出走 Web 同款视图层,页面类方法会输出 HTML;运维脚本优先调用"无界面副作用"的方法(refreshStats、cron run、backup 等)。与 curl 相比 ztcli 免登录免 Referer(CLI 模式绕过 CSRF),适合放进 crontab。
三、初始化维护脚本:init.sh / init.php
官方帮助手册"初始化管理脚本"一节约定:bin/init.sh 接受 PHP 路径与站点 URL 两个参数,内部调用 bin/php/init.php,依据 zt_cron 表与系统任务生成全部维护脚本。实测:
$ /opt/zbox/bin/php /apps/zentao/bin/php/init.php /opt/zbox/bin/php http://127.0.0.1:8143
metricupdatedashboardmetriclib.sh ok.
mailasyncsend.sh ok.
webhookasyncsend.sh ok.
admindeletelog.sh ok.
errorlogdeletelog.sh ok.
programrefreshstats.sh ok.
productrefreshstats.sh ok.
weeklycreatecyclereport.sh ok.
backupbackup.sh ok.
todocreatecycle.sh ok.
metricupdatemetriclib.sh ok.
reportremind.sh ok.
executioncomputetaskeffort.sh ok.
executioncomputeburn.sh ok.
executioncomputecfd.sh ok.
auditplanajaxcreatecycleauditplan.sh ok.
zaisyncvectorization.sh ok.
airuntimeragents.sh ok.
cron.sh ok
ztcli.sh ok
生成脚本落在 bin/ 下,同时产出 crontab 清单 bin/cron/sys.cron(节选):
#min hour day month week command.
0 * * * * /apps/zentao/bin/metricupdatedashboardmetriclib.sh #计算仪表盘数据
*/1 * * * * /apps/zentao/bin/mailasyncsend.sh #异步发信
*/5 * * * * /apps/zentao/bin/admindeletelog.sh #删除过期日志
0 0 * * * /apps/zentao/bin/backupbackup.sh #每日自动备份
...
一键安装包(zbox)用户交互式执行:cd /opt/zbox/app/zentao/bin && ./init.sh,按提示输入 PHP 路径(/opt/zbox/bin/php)与访问 URL 即可。重新初始化会覆盖同名脚本,自定义过脚本的读者升级后需重新执行并复核。
四、命令行备份与恢复
禅道备份四要素(官方备份文档约定):配置文件(my.php)、修改过的代码、数据库、附件(www/data)。四种实测方式按场景选用:
4.1 后台界面备份
后台 → 系统设置 → 备份,点击开始备份(或直接访问 index.php?m=backup&f=backup),实测返回:
备份成功!
产物在 /apps/zentao/tmp/backup/(即 /data/zentao/tmp/backup/):
20261027184439822_6.sql.php # 数据库归档(PHP 头伪装,防止直链下载)
20261027184439822_6.file/ # 附件目录
summary # JSON 摘要:文件数/大小/错误清单
4.2 脚本备份(init.php 生成)
$ cat /apps/zentao/bin/backupbackup.sh
/opt/zbox/bin/php /apps/zentao/bin/ztcli 'http://127.0.0.1:8143/index.php?m=backup&f=backup'
$ sh /apps/zentao/bin/backupbackup.sh
备份成功!
实测该次备份除 sql/file 外还生成了 20261027184629522_6.code/ 目录(20013 个文件、约 277MB,应用代码全量),summary 同步记录三项产物——需要代码要素备份的场景直接复用该脚本;磁盘紧张时可在备份设置(index.php?m=backup&f=setting)中关闭代码备份。
4.3 mysqldump 手工备份
最小化的数据库级备份,实测:
$ /opt/zbox/run/mysql/mysqldump -uroot -p123456 zentao > /data/zentao/dump/zentao-20261027.sql
$ ls -la /data/zentao/dump/
-rw-r--r-- 1 root root 2372571 Oct 27 18:47 zentao-20261027.sql
$ grep -c 'INSERT INTO' /data/zentao/dump/zentao-20261027.sql
70
注意二进制路径:22.6 镜像中 mysqldump 位于 /opt/zbox/run/mysql/(不带 bin 子目录),写成 /opt/zbox/run/mysql/bin/mysqldump 会报 not found。
4.4 整体快照
停服务后整拷 /data 卷(配置+附件+数据库+日志全含),是最稳的迁移/大版本升级前快照方式。
4.5 恢复
- 界面恢复:备份页面每条记录自带"恢复"按钮(自动执行 restoreSQL/restoreFile);
- SQL 恢复:
/opt/zbox/run/mysql/mysql -uroot -p123456 zentao < zentao-20261027.sql; - .sql.php 归档:去掉 PHP 头后解压得到 SQL 与附件包,按上条导入;
- 整体快照:反向覆盖
/data后启动。
五、计划任务运维
5.1 任务清单(zt_cron 表实测)
后台 → 系统设置 → 定时 对应 zt_cron 表,22.6 出厂内置 14 项(节选实测记录):
| id | 周期 | 任务 | 状态 |
|---|---|---|---|
| 2 | 每小时整点 | metric updateDashboardMetricLib | normal |
| 3 | 每 1 分钟 | mail asyncSend(异步发信) | normal |
| 4 | 每 1 分钟 | webhook asyncSend | normal |
| 5 | 每 5 分钟 | admin deleteLog(过期日志清理) | normal |
| 7/8 | 每 5 分钟 | program/product refreshStats | normal |
| 9 | 每日 00:00 | weekly createCycleReport | normal |
| 10 | 每日 00:30 | backup backup(自动备份) | normal |
| 11 | 每日 01:00 | todo createCycle | normal |
| 13 | 每日 07:30 | effort remindNotRecord | stop(出厂即停用) |
开关操作在后台"定时"页面完成(或 SQL 改 zt_cron.status)。邮件发不出、统计不刷新,先来这页确认对应任务状态。
5.2 执行机制与手动触发
任务调度链:zt_cron 定义 → crond 守护轮询(系统内置托管)→ 调用 ztcli 形式的模块方法。手动触发单个任务的最稳方式:
$ /opt/zbox/bin/php /apps/zentao/bin/ztcli 'http://127.0.0.1:8143/index.php?m=backup&f=backup'
5.3 crond.php 直跑报错实录
直接以 PHP CLI 运行守护脚本报错:
$ /opt/zbox/bin/php /apps/zentao/bin/php/crond.php
Fatal error: Uncaught Error: Attempt to assign property "version" on null in
/apps/zentao/config/config.php:19
原因:22.6 的 config/config.php 期望调用方先完成 $config 对象初始化,crond.php 的裸 include 引导顺序与其不匹配(一键安装包环境由面板进程拉起,无此问题)。容器形态请勿手工直跑 crond.php,计划任务交给系统内置机制,手动触发用 ztcli 调方法。
六、缓存与日志
$ /opt/zbox/bin/php /apps/zentao/bin/php/cleancache.php
Cleaned 0 cache files.
日志目录 /data/zentao/tmp/log/ 与 PHP 错误日志 /data/php/log/error.log 由定时任务 admin deleteLog(每 5 分钟)按保留期自动清理;手工清理直接删除目录内过期文件,勿删目录本身。
七、API v1 调用实录
禅道 REST API v1 的两个核心步骤实测如下(完整对象清单见官方 API 文档,覆盖产品/需求/任务/Bug 等全部资源)。
7.1 获取 token
$ curl -s -X POST "http://127.0.0.1:8143/api.php/v1/tokens" \
-H "Content-Type: application/json" \
-d '{"account":"admin","password":"Q1w2e3r4"}'
{"token":"de3a348c35626ae822508124471deb83"} # HTTP 201
URL 形态注意:实测必须使用 /api.php/v1/tokens(路径式、不带 .json 后缀);写成查询串 ?v1=tokens.json 或路径加 .json 均失败(返回 401/404,见排障实录 2)。
7.2 携带 token 调用业务接口
$ curl -s "http://127.0.0.1:8143/api.php/v1/products" -H "Token: de3a348c35626ae822508124471deb83"
{"page":1,"total":3,"limit":100,
"products":[
{"id":3,"name":"智慧园区管理平台","status":"active",...},
{"id":1,"name":"公司企业网站建设","status":"normal",...},
{"id":2,"name":"企业内部工时管理系统","status":"normal",...}]}
认证头名称为 Token(值为 tokens 接口返回的串),token 即服务端会话标识,过期后重新获取。
7.3 浏览器登录的脚本等价实现
接口登录(非 API 通道)需复现浏览器的密码变换,可直接复用以下实测脚本骨架:
#!/bin/bash
BASE="http://127.0.0.1:8143"
RAND=$(curl -s -c ck.txt "$BASE/index.php?m=user&f=refreshRandom")
# 密码变换:md5(md5(明文) + rand)
PH=$(python3 -c "import hashlib;print(hashlib.md5((hashlib.md5(b'Q1w2e3r4').hexdigest()+'$RAND').encode()).hexdigest())")
curl -s -b ck.txt -c ck.txt -X POST "$BASE/index.php?m=user&f=login" \
-e "$BASE/index.php?m=user&f=login" \
--data-urlencode "account=admin" \
--data-urlencode "password=$PH" \
--data-urlencode "passwordStrength=1" \
--data-urlencode "referer=/" \
--data-urlencode "verifyRand=$RAND" \
--data-urlencode "keepLogin=on"
# 输出 <script>self.location='/';</script> 即登录成功,后续请求携带 ck.txt
八、日常运维巡检清单
结合以上工具,给出实测有效的巡检动作:
- 备份健康:
ls /data/zentao/tmp/backup/最新产物时间戳 +summary无 errorFiles; - 计划任务:后台"定时"页无异常状态项,
zt_cron.lastTime持续更新; - 磁盘水位:
du -sh /data/zentao/tmp/backup /data/zentao/www/data /data/mysql三大目录; - 日志巡检:
/data/php/log/error.log尾部无新增 Fatal; - 版本核对:站点页脚版本号与
.version安装记录一致。
九、排障实录
1)crond.php 直跑 Fatal(见 5.3):config.php:19 Attempt to assign property "version" on null。不修复不绕过,改用 ztcli 触发。
2)API URL 形态错误返回 401/404
现象:/api.php?v1=tokens.json 返回 {"error":"EMPTY_ENTRY"}(404),/api.php/v1/tokens.json 返回 {"error":"Unauthorized"}(401)。
原因:v1 路由表按路径匹配 /tokens 精确串,查询串形态与 .json 后缀均无法命中,请求落入 error 入口再被会话检查拦截。
解法:统一使用 /api.php/v1/<entry>(无后缀)+ JSON body + Token 响应头。
3)mysqldump 路径不存在
现象:/opt/zbox/run/mysql/bin/mysqldump: not found。
原因:该镜像二进制直接放在 /opt/zbox/run/mysql/ 下(无 bin 子目录)。find / -name mysqldump 定位是通用解法。
4)脚本登录被 302 打回
原因与解法见部署篇排障 4 与本文 7.3:先 refreshRandom 取随机数,密码按 md5(md5(明文)+rand) 变换并回传 verifyRand。
十、小结
22.6 的运维面可归纳为三个入口:ztcli(免登录触发任意只读/后台方法)、init.php 生成的脚本族(备份/统计/清理的固化包装)、API v1(外部系统集成的正规通道)。配合配置篇的 my.php 体系与部署篇的数据卷布局,即可覆盖禅道从部署到长期运维的完整生命周期。