HortusFox 6.4 常用 CLI 命令与工具详解
HortusFox 6.4 命令行工具 asatru 全命令实测详解:31 条命令(框架 16 + 应用 15)逐个执行与回显、迁移/备份/主题/脚手架四族用法、exit code 恒 0 与 make:command 类名等六条实测踩坑、开发服务器与定时任务命令行视角。
HortusFox 6.4 常用 CLI 命令与工具详解
本文全部命令与输出均在实测环境逐条执行并取自真实回显(ANSI 颜色码已去除,语义不变):Ubuntu 24.04.5 LTS、HortusFox v6.4(截至 2026-10-28 的最新稳定版)、PHP 8.3.6、MariaDB 11.4.13,项目根目录
/var/www/hortusfox,示例管理员账号 admin / q1w2e3r4。
HortusFox 没有独立的管理脚本,全部命令行能力集中在一个入口:项目根目录的 asatru 文件(PHP 脚本),用法 php asatru <命令> [参数]。它由自研 Asatru 框架的 console 组件驱动,内置 16 条框架命令,加上应用层在 app/config/commands.php 注册的 15 条命令,共 31 条。本文逐条实测这 31 条命令——包括几条破坏性命令的行为边界与还原过程——并沉淀六条实测踩坑。
前置阅读:部署方法与首次 migrate:fresh 建表见 《HortusFox 安装部署指南》;本文涉及的配置参数语义(APP_DEBUG、DB_* 等)见 《HortusFox 6.4 配置参数详解》;项目背景见 《HortusFox 介绍与选型指南》。
一、CLI 入口与调用约定
三条硬性调用约定,全部有实测依据:
- 必须先进入项目根目录:CLI 入口用相对路径
file_exists('.env')加载配置,在别处执行php /var/www/hortusfox/asatru会因读不到.env而报调试模式错误(详见部署指南排障实录第 1 条); - APP_DEBUG 必须为 true:调试关闭时 CLI 整体拒绝工作,实测回显
CLI tool is only available in debug mode; - 所有命令退出码恒为 0:包括明确报错的场景(第一节实测验证)。自动化脚本不能靠
$?判断成败,必须解析输出内容。
无参数执行 php asatru 即帮助文本,实测输出全部 31 条命令:
$ php asatru
Asatru PHP by Daniel Brendel (dbrendel1988@gmail.com) - CLI interface
The following commands are available:
+ help: Displays this help text
+ make:model <name>: Creates a new model with migration
+ make:module <name> <opt:args[]>: Creates a new module for business logics
+ make:controller <name>: Creates a new controller
+ make:language <ident>: Creates a new language folder with app.php
+ make:validator <name> <ident>: Creates a new validator
+ make:event <name> <handler>: Creates a new event handler
+ make:command <name>: Creates a new command
+ make:auth: Creates new authentication model and migration
+ make:cache: Creates new cache model and migration
+ make:test <name>: Creates a new test case
+ migrate:fresh: Drops all migrations and creates all new
+ migrate:list: Creates only all new created migrations
+ migrate:drop: Drops all migrations
+ routes:list: Lists all registered routes
+ serve <port>: Spawns a development server. If port is not provided it uses port 8000
+ product:version: Show current product version
+ product:info: Show product and system info
+ migrate:version: Incrementially update the current product version
+ migrate:email: Update product contact E-Mail address
+ migrate:upgrade: Perform upgrade from last version to current version
+ migrate:specific: Perform version specific migration upgrade
+ calendar:classes: Add default calendar classes
+ plants:attributes: Add default plant attributes
+ cache:clear: Clear the entire cache
+ theme:list: List all installed themes
+ theme:install: Install a theme
+ theme:remove: Remove an installed theme
+ backup:export: Export workspace data as a backup archive
+ backup:import: Import workspace data from a backup archive
+ aquashell:config: Create config file for AquaShell scripts
前 16 条来自框架(help 到 serve),后 15 条是 HortusFox 应用命令(product:version 起)。未注册的命令实测报 Command bogus:cmd is unknown。
二、信息与诊断命令
2.1 product:version
$ php asatru product:version
Current product version: 6.4
读取的是 app/config/version.php(内容 return '6.4';),是升级操作后核对版本的第一命令。
2.2 product:info
一次性输出运行环境全景,实测:
$ php asatru product:info
HortusFox v6.4 Debug
Developed by Daniel Brendel (daniel@danielbrendel.com)
PHP Version: 8.3.6
MySQL Version: 11.4.13-MariaDB-ubu2404
Server: Linux #38-Ubuntu SMP PREEMPT_DYNAMIC Fri Sep 4 09:10:14 UTC 2026 x86_64
Timezone: 2026-10-28 10:45 (UTC)
GitHub URL: https://github.com/danielbrendel/hortusfox-web
Service URL: https://www.hortusfox.com
Sponsoring URL: https://github.com/sponsors/danielbrendel
Donation URL: https://ko-fi.com/danielbrendel
MySQL Version 实测显示的是 MariaDB 版本号——mysql 协议驱动不区分发行版。部署验收时这条命令输出正常即代表「代码 → 依赖 → .env → 数据库」链路全通。
2.3 routes:list
打印 app/config/routes.php 注册的全部路由,每行格式 [方法] 路径 -> 控制器@方法,实测共 177 条(节选):
$ php asatru routes:list
[GET] / -> index@index
[GET] /auth -> index@auth
[POST] /login -> index@login
[ANY] /logout -> index@logout
[GET] /plants/details/{id} -> plants@view_plant_details
[POST] /admin/environment/save -> admin@save_environment
[POST] /cronjob/tasks/overdue -> cronjobs@overdue_tasks
[ANY] /api/plants/get -> api@get_plant
[POST] /export/start -> backup@export
[ANY] $404 -> error404@index
177 routes found in /app/config/routes.php
排查"某 URL 404"时先看这条:路径是否存在、方法是否匹配(GET/POST/ANY)一目了然。全部 177 条的分组解读(含 cronjob 与 REST API 段)见《HortusFox 6.4 配置参数详解》第九、十节。
三、数据库迁移命令族
migrate 族共 6 条,两条重建型(fresh/drop)、四条增量/元数据型(list/version/email/upgrade/specific 中前四条)。fresh 与 drop 破坏性极强:fresh 会删除全部 27 张表重建(部署指南第三节已用它完成首次建表),drop 直接清库——这两条本轮不再重复执行,生产环境仅限初始化与放弃数据的场景。
3.1 migrate:list(增量应用迁移文件)
$ php asatru migrate:list
The database has been listly migrated!
只应用"尚未执行过"的迁移文件。日常把 git pull 拉来的新迁移落库就用它,比 fresh 安全得多。
3.2 migrate:version(产品版本号步进)
把版本号 +0.1 并同步改写 5 个文件 + 重写 version.php:.env、.env.example、.env.testing、public/install/index.php、scripts/install.dnys 中的 APP_VERSION="旧值",以及 app/config/version.php。实测(执行后立即还原):
$ php asatru migrate:version
Upgraded from 6.4 to 6.5
$ php asatru product:version
Current product version: 6.5
$ grep APP_VERSION .env
APP_VERSION="6.5"
这条命令是给开发者发新版本用的,不是给运维升级用的——运维升级走 migrate:upgrade(3.4 节)。误执行后还原方法:git checkout -- .env.example .env.testing app/config/version.php public/install/index.php scripts/install.dnys,.env 不在 git 里需手工把 APP_VERSION 改回(实测还原后 product:version 恢复 6.4)。
3.3 migrate:email(联系邮箱替换)
同理同步替换 6 个文件(比 version 多一个 SECURITY.md)里的联系邮箱。先实测非法参数:
$ php asatru migrate:email not-an-email
Operation failed: Invalid address specified for new mailbox: not-an-email
合法路径实测(执行后已还原):
$ php asatru migrate:email admin@hortusfox.local
Upgraded from daniel@danielbrendel.com to admin@hortusfox.local
$ grep APP_CONTACT .env
APP_CONTACT="admin@hortusfox.local"
它做的是全文替换:6 个文件里所有出现的旧地址都换成新地址,因此只适用于把项目自带的作者邮箱换成自己的运维场景。
3.4 migrate:upgrade(按版本区间执行升级迁移)
读取 app/migrations/verhist.json 里的上次升级记录,从那里步进到当前版本,逐版本调用 UpgradeModule。实测:
$ php asatru migrate:upgrade
Upgrading to 6.4...
[6.4] Done!
3.5 migrate:specific(指定版本迁移)
$ php asatru migrate:specific 6.4
[6.4] Done!
$ php asatru migrate:specific 99.9
[99.9] Nothing to migrate or upgrade.
参数是两位版本号(如 6.4),无该版本的迁移内容时输出 Nothing to migrate or upgrade.,无副作用。
升级组合拳(拉新代码后):git pull && composer install && php asatru migrate:upgrade && php asatru cache:clear——与部署指南第十三节的升级路径一致,升级前先用 backup:export 兜底(第六节)。
四、初始化数据命令
4.1 plants:attributes(默认植物属性)
无参数时幂等静默:默认属性已存在则什么都不输出、退出码 0(部署指南第六节提过"没输出不是没执行")。带 --force 则清空重建,实测:
$ php asatru plants:attributes --force
Dropping previous plant attributes.
Adding default plant attribute: last_watered
Adding default plant attribute: last_repotted
Adding default plant attribute: last_fertilised
Adding default plant attribute: lifespan
Adding default plant attribute: hardy
Adding default plant attribute: cutting_month
Adding default plant attribute: date_of_purchase
Adding default plant attribute: humidity
Adding default plant attribute: light_level
Adding default plant attribute: health_state
10 个默认属性(最近浇水/换盆/施肥、寿命、耐寒性、修剪月份、购入日期、湿度、光照、健康状态)即植物详情页的追踪字段。
4.2 calendar:classes(默认日历分类)
同款幂等语义,--force 实测重建 8 个分类,每类带两个 RGB 色值(普通态/高亮态):
$ php asatru calendar:classes --force
Dropping previous calendar classes.
Adding calendar class: water app.calendar_class_water rgb(76, 135, 195) rgb(131, 183, 251)
Adding calendar class: repot app.calendar_class_repot rgb(150, 115, 74) rgb(222, 183, 143)
Adding calendar class: fertilise app.calendar_class_fertilise rgb(135, 195, 102) rgb(205, 240, 167)
Adding calendar class: purchase app.calendar_class_purchase rgb(230, 220, 90) rgb(255, 250, 185)
Adding calendar class: cut app.calendar_class_cut rgb(235, 163, 67) rgb(230, 125, 50)
Adding calendar class: treat app.calendar_class_treat rgb(200, 111, 111) rgb(255, 150, 150)
Adding calendar class: harvest app.calendar_class_harvest rgb(72, 243, 65) rgb(180, 250, 155)
Adding calendar class: other app.calendar_class_other rgb(150, 150, 150) rgb(200, 200, 200)
浇水、换盆、施肥、采购、修剪、施药、收获、其他——与任务系统的养护动作一一对应。误删分类后 --force 一键找回。
4.3 aquashell:config(AquaShell 安装脚本配置)
为官方 AquaShell 自动安装脚本生成两份配置,实测:
$ php asatru aquashell:config
Successfully created AquaShell configuration files.
生成 scripts/tmp/urls.conf.dnys(四个官方 URL)与 scripts/tmp/db.conf.dnys(数据库连接五项)。注意 db.conf.dnys 里 DATABASE_PASS 是 .env 口令的明文(实测生成文件即含 const DATABASE_PASS string <= "q1w2e3r4";),生成后应立即删除或收紧目录权限,不要留在生产文件树里。普通部署用不到这条命令,它是给要用官方脚本再装一台的运维准备物料的。
五、缓存与主题命令
5.1 cache:clear
$ php asatru cache:clear
Clearing cache...
Done!
清空框架缓存表(CacheModel 对应的数据)。升级后、改完 app/config 后跑一次,属于安全操作。管理后台也有等价按钮(POST /admin/cache/clear)。
5.2 theme:list / theme:install / theme:remove(主题三件套)
主题商店托管在官方站点(APP_SERVICE_URL/downloads/<主题名>.zip),实测商店当前提供 17 个主题:autumn_forest、autumn_hill、blossom、botanicals、castles、flowers、frisky、minecraft、night、pixelart、prehistoricals、shelf、shrooms、spooky_forest、spring、winter、xmas。
初始状态只有内置主题,实测安装→列出→移除全流程:
$ php asatru theme:list
Installed themes:
- default v1.0 | Author: Daniel Brendel | Contact: https://www.hortusfox.com
$ php asatru theme:install night
Attempting to install night...
Downloading 'https://www.hortusfox.com/downloads/night.zip'...
Extracting archive...
Done.
$ php asatru theme:list
Installed themes:
- default v1.0 | Author: Daniel Brendel | Contact: https://www.hortusfox.com
- night v1.0 | Author: Kaleben0 | Contact: https://www.hortusfox.com
$ php asatru theme:remove night
Attempting to remove night...
Done.
主题落在 public/themes/<名称>/(含 theme.json 元数据),安装后由用户在个人资料页选用(框架按用户资料里的主题字段加载,见 app/controller/_base.php)。缺参数与主题不存在的报错实测:Invalid argument: please provide the name of the theme to install。管理后台也支持 zip 上传安装第三方主题(POST /admin/themes/import),CLI 装不了的自定义包走那条路。
六、备份与恢复命令
6.1 backup:export(导出工作区归档)
$ php asatru backup:export
Creating backup archive...
Backup archive created: /var/www/hortusfox/public/backup/hf_backup_2026-10-28_10-46-06.zip
归档落在 public/backup/hf_backup_<时间戳>.zip,包含六个数据域:locations(位置)、plants(植物+属性+附件+日志)、gallery(照片库)、tasks(任务)、inventory(库存)、calendar(日历)。命令支持分段选择:不带参数全量导出;带 plants=0 这类参数则把对应域关掉(其余保持开),例如只要位置和日历:php asatru backup:export plants=0 gallery=0 tasks=0 inventory=0。
升级前、大规模改动前、以及配合管理后台 auto_backup 的定时归档(见配置详解篇 10.9 节),都是这条命令或它的 HTTP 等价物在工作。
6.2 backup:import(从归档恢复)
三条实测路径:
$ php asatru backup:import
Error: Please specify the import file (located in /var/www/hortusfox/public/backup)
$ php asatru backup:import no_such_file.zip
Error: The file /var/www/hortusfox/public/backup/no_such_file.zip does not exist
$ php asatru backup:import hf_backup_2026-10-28_10-46-06.zip
Importing backup from /var/www/hortusfox/public/backup/hf_backup_2026-10-28_10-46-06.zip...
Import succeeded
要点:
- 归档必须放在
public/backup/下,参数只给文件名(可省 .zip 后缀); - 同样支持分段参数(
plants=0 ...跳过某域); - 恢复采用
INSERT IGNORE语义——实测把刚导出的归档原样导回,Import succeeded且数据无重复无变化(id 冲突行跳过,仅补缺失数据)。因此它是"补数据"而非"回滚到快照":要把某株植物恢复到旧状态,得先删掉现状再导入,指望直接覆盖回去是不行的; - 导入后同样建议
php asatru cache:clear。
七、脚手架命令(make:*)
make 族为二次开发生成代码骨架。实测三条最常用的:
7.1 make:command(自定义 CLI 命令)——含一个大坑
帮助文本写的是"指定命令的类名",实测先踩坑再验证正确姿势:
$ php asatru make:command
You must specify the class name of the command
$ php asatru make:command demo:hello
Command class has been created!
坑:把冒号命令名当类名传入,会生成 app/commands/demo:hello.php,其内容 class demo:hello implements ... 是非法 PHP(类名不能含冒号),且该命令注册前执行报 Command demo:hello is unknown。正确姿势三步(实测):
$ php asatru make:command DemoHello
Command class has been created!
生成的 app/commands/DemoHello.php 是可用的空处理器(class DemoHello implements Asatru\Commands\Command,handle($args) 空方法体);在 app/config/commands.php 注册一行:
['demo:hello', 'Demo command for CLI testing', 'DemoHello']
随后 php asatru demo:hello 即可调用(实测静默执行、退出码 0)。自研命令里用 $args->get(0)->getValue() 取参数、env() 读配置,与官方 15 条命令的源码结构完全一致(app/commands/ 下可参照)。
7.2 make:model / make:controller
$ php asatru make:model DemoCat
Model and migration files have been created!
$ php asatru make:controller DemoCtl
The controller has been created!
make:model 一次生成两个文件:app/models/DemoCat.php(模型类)与 app/migrations/DemoCat.php(迁移类,up() 方法里逐列 add(...) 声明表结构、create() 落表,down() 反向 drop),跑 migrate:list 即可建表。实测生成的迁移骨架(节选):
public function up()
{
$this->database = new Asatru\Database\Migration('DemoCat', $this->connection);
$this->database->drop();
$this->database->add('id INT NOT NULL AUTO_INCREMENT PRIMARY KEY');
$this->database->add('created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP');
$this->database->create();
}
其余脚手架按帮助文本用途列出:make:module(业务逻辑模块)、make:language(新增语言目录)、make:validator(输入校验器)、make:event(事件处理器)、make:auth / make:cache(认证/缓存组件与迁移)、make:test(测试用例)。本文实测的三个脚手架文件均已删除、未遗留。
八、serve:内置开发服务器
$ php asatru serve 8088
Local development server started at localhost:8088
底层执行 php -S localhost:8088 -t public/,用于无 nginx 的快速验证。实测两个细节:只监听 IPv6 回环 [::1]——curl http://127.0.0.1:8088/ 连接失败(http 000),curl 'http://[::1]:8088/' 正常返回 HTTP/1.1 302 Found(未登录跳认证页,X-Powered-By: PHP/8.3.6);生产环境仍应使用 nginx + PHP-FPM(部署指南第七节),serve 仅作临时调试。
九、定时任务的命令行视角
HortusFox 的定时提醒不靠 CLI 常驻进程,而是外部周期调用 HTTP 端点(POST /cronjob/tasks/overdue、tasks/tomorrow、tasks/recurring、calendar/reminder、backup/auto,携带 AppModel 中的 cronjob_pw 口令)。命令行在这条链路上的角色是验证与兜底:routes:list 确认端点注册(第二节)、curl 单端点连通性测试与 systemd timer 托管全流程见《HortusFox 安装部署指南》第十一节,口令管理见《HortusFox 6.4 配置参数详解》第十节。
十、排障实录
1. php asatru list 报 "Command list is unknown"。
CLI 没有 list 子命令——list 被当作自定义命令去注册表查找,找不到就报未知。看命令清单的正确姿势是无参数执行 php asatru。
2. make:command 传冒号命令名,生成的文件是非法 PHP。
php asatru make:command demo:hello 生成 class demo:hello,PHP 语法层面直接不合法,且不报错、静默产出坏文件。参数必须是合法类名(如 DemoHello),冒号名只出现在 commands.php 注册表里。误生成的 app/commands/demo:hello.php 手工删除即可。
3. serve 起来后 127.0.0.1 连不上。
php -S localhost:8088 在该环境解析为 IPv6 [::1] 监听。用 curl 'http://[::1]:8088/' 或改绑 0.0.0.0(直接用底层命令 php -S 0.0.0.0:8088 -t public/)。
4. 脚本里判断 $? 恒为 0,错误静默通过。
实测所有错误路径(未知命令、缺参数、文件不存在、非法邮箱)退出码都是 0——console 入口统一 exit(0)。自动化必须 grep 关键输出(如 Import succeeded、Operation failed)判断结果,或者干脆依赖 HTTP 端点的 {"code":200}(见部署指南第十一节)。
5. migrate:version/migrate:email 是"多文件全文替换",还原麻烦。
两条命令一次改 5-6 个文件(含 .env.example、SECURITY.md 等),测试时必须记录原值或先 git status 确认工作区干净——本文实测即按"执行→验证→git checkout 还原受管文件、手工还原 .env"流程操作,最终 product:version 恢复 6.4、APP_CONTACT 恢复原值。
6. 手改版本号出现两处不一致。
版本号存两处:.env 的 APP_VERSION 与 app/config/version.php,product:info 标题行还拼了 APP_DEBUG。手改只改一处就会出现"product:version 与 product:info 显示不一致"的错觉——版本号永远交给 migrate:version 维护,别手改。
十一、小结
31 条命令按运维视角归四类就够用:日常诊断(product:version/info、routes:list、cache:clear)、升级迁移(backup:export 先行 → git pull + composer install → migrate:upgrade → cache:clear)、数据修复(plants:attributes/calendar:classes --force、backup:import 补数据)、二次开发(make:* + 自定义命令注册)。三条纪律:进项目根目录再执行、别信退出码要解析输出、fresh/drop/migrate:version 这类破坏性命令在敲回车前先想清楚影响面。
本文与《HortusFox 6.4 配置参数详解》互为表里:命令改的多数是配置,配置的行为要靠命令来验证。部署与系统级托管(nginx/PHP-FPM/systemd timer)见《HortusFox 安装部署指南》,选型与功能全景见《HortusFox 介绍与选型指南》。