Meetable latest 常用 CLI 命令与工具详解
Meetable latest(main@7d2d22ab,Laravel 12.69.1)CLI 与工具链实测详解:docker compose 运维命令、artisan 标准/自定义 17 条命令逐字回显(user:create 发 token、user:passkey-link 一次性登录链接、backup:all JSON 导出)、Bearer Token API 建事件权限闭环与 iCal/RSVP 工具面(2026-11-02)
Meetable latest 常用 CLI 命令与工具详解
版本标识同 C1:latest = main@7d2d22ab7f85(2026-10-16),容器内 Laravel 12.69.1 / PHP 8.2.34。本文所有命令均在实测栈(
/opt/data/quzuo/tmp/meetable/,端口 8158)逐字执行,回显原样记录。注意:Meetable 是 Laravel 应用,没有 Rails console/rake,对应物是php artisan tinker与php artisan命令族(任务书预设的 Rails 工具链按实替换)。
一、docker compose 运维命令面
| 命令 | 用途 | 实测备注 |
|---|---|---|
docker compose up -d | 首启/改 .env 或 compose 后重建 | compose 检测 env_file 内容变化自动 recreate |
docker compose ps | 四容器状态 | app/worker/db/redis |
docker compose logs -f app | 看迁移/Apache 日志 | entrypoint 等库→migrate→apache |
docker compose logs worker | 队列消费日志 | 头像/webmention 异步任务 |
docker compose restart app | 清进程内静态缓存(改库后) | C1 §五实测必需动作 |
docker compose pull && docker compose up -d | 升级(滚动 main) | 先备份卷,见 B2 §九 |
docker compose down / down -v | 停栈 / 连数据卷一起删 | -v 会删 meetable_db,慎用 |
docker exec -it meetable-app-1 sh | 进容器 | 应用根目录 /var/www/html |
二、artisan 标准命令(实测回显)
在宿主机统一用 docker exec meetable-app-1 php artisan <cmd> 调用:
$ php artisan --version
Laravel Framework 12.69.1
$ php artisan about
Application Name .... Meetable Laravel Version .... 12.69.1
PHP Version .......... 8.2.34 Composer Version ... 2.10.3
Environment .......... production Debug Mode ...... OFF
URL .................. 127.0.0.1:8158 Maintenance Mode ... OFF
Config/Events/Routes/Views 全部 NOT CACHED(生产可 php artisan config:cache 提速)
Cache .... redis Database .... mysql Mail .... log
$ php artisan migrate:status
2026_10_15_000000_response_photos_removed ......... [1] Ran (60+ 条全 Ran)
$ php artisan key:generate --show
base64:G10in52Tbrkk6P+DPZ1T75Sjx7dGqkMv1lv8izx6JQQ=
# 只打印新 key 不写文件——Docker 形态 .env 在宿主机,禁用默认的原地写入
$ php artisan schedule:list
* * * * * php artisan event:notify .......... Next Due: 35 seconds from now
* * * * * php artisan discord:notify ........ Next Due: 35 seconds from now
* * * * * php artisan discord:sync-events ... Next Due: 35 seconds from now
0 0 * * * php artisan recurring:schedule ....... Next Due: 4 hours from now
# ⚠️ 栈内无进程执行 schedule:run,这 4 个任务默认不会跑(B2 §八补位)
$ php artisan queue:work --stop-when-empty
# 处理完立即退出;配合 tinker 查 DB::table('jobs')->count() = 0 pending
$ php artisan event:list | grep -i webmention
App\Events\WebmentionReceived ......... ⇂ App\Listeners\WebmentionReceivedListener (ShouldQueue)
tinker(替代 Rails console 的数据操作通道)
模型命名空间是旧式 App\User/App\Event/App\Setting(无 App\Models\*);create() 受 mass-assignment 限制,脚本化建数据用 forceCreate:
docker exec meetable-app-1 php artisan tinker --execute="
App\User::forceCreate(['name'=>'Admin','email'=>'a@e.org','identifier'=>'http://e.org/a','is_admin'=>1]);
App\Setting::set('auth_hide_login','1');"
⚠️ 手工建事件 key 必须恰好 12 位字母数字(Event::find_from_url 正则硬约束,B2 §5.3 踩坑);直接改 settings 表后需 docker restart meetable-app-1 清静态缓存(C1 §五)。
三、自定义命令全清单(app/Console/Commands/ 17 个文件实查)
| 命令 | 描述(artisan list 原文) | 使用场景 |
|---|---|---|
user:create {url} | Create a user account and API token | 无浏览器建用户/拿 API token |
user:passkey-link {email} | Print a one-time link that lets a user register a new passkey | headless 管理员登录入口 |
backup:all | Back up all events into a folder on disk | 事件/用户 JSON 导出 |
webmention:refresh | Fetch all webmentions again and re-parse | webmention 抓取修复 |
event:notify | Send notifications for upcoming events | 会前提醒(scheduler 任务) |
discord:notify / discord:sync-events | Discord 频道预告 / 服务器事件列表同步 | Discord 集成运维 |
recurring:schedule | Create events from the scheduled recurring events | 周期事件实例生成(每日 0 点) |
user:fetch_details {url?} | 拉取用户 h-card 资料 | 资料修复 |
migrate:settings | Migrate config settings from .env to the database | 旧 .env 站点配置一次性入库 |
migrate:revision_history / migrate:event_sort_date / migrate:response_photos / migrate:response_author_images / migrate:user_images / migrate:resize_user_images | 历史数据修补 | 升级排障备用 |
3.1 user:create + API token(逐字回显)
$ docker exec meetable-app-1 php artisan user:create http://quzuo.net/cli-user
API Token: wuBY1XhPjScJ03Y7B5l4fnfxa6eHhhIRDIHHOHsD2DbBsaXtJUBhPslJ790YBEHZPjoK6o0ppxzHdeCf
token 存 users.api_token,仅显示一次,立即用于 Authorization: Bearer <token>(§四)。
3.2 user:passkey-link(一次性登录链接)
$ docker exec meetable-app-1 php artisan user:passkey-link admin@quzuo.net
Open this link within 30 minutes to register a new passkey for Admin. It can only be used once.
http://127.0.0.1:8158/auth/passkey-link/1?expires=1793563734&nonce=tWcu...&signature=00d7...
签名 URL(middleware('signed')),30 分钟有效、单次使用,浏览器打开即可注册 passkey——这是无头环境给管理员开登录凭据的官方通道,比在服务器上直接操作 DB 干净得多。
3.3 backup:all(JSON 导出)
$ docker exec meetable-app-1 php artisan backup:all
Backing up event to events/2026/12/api-created-event-ldtH5xXyvNhd.json
Backing up user to users/1.json
Backing up user http://quzuo.net/cli-user to users/2.json
# 产物在卷 meetable_storage 的 storage/app/{events,users}/ 下
注意这是逻辑导出(事件/用户 JSON),不是数据库备份;完整备份仍需 mariadb dump + 存储卷(B2 §九)。
四、HTTP API 工具链(routes/api.php 实查 + 权限闭环实测)
auth:api Bearer token 三端点 + 公开端点:
$ curl -H "Authorization: Bearer $TOKEN" http://127.0.0.1:8158/api/user
{"identifier":"http://quzuo.net/cli-user","url":"http://quzuo.net/cli-user","email":null,"name":null,"photo":null,"default_timezone":null}
# 建事件:普通用户被 ALLOW_MANAGE_EVENTS=admins 拦截
$ curl -X POST -H "Authorization: Bearer $TOKEN" -d 'name=API Created Event&start_date=2026-12-01 10:00&timezone=Asia/Shanghai' http://127.0.0.1:8158/api/add-event
→ HTTP 403 Forbidden(页面标题 Forbidden)
# tinker 提升该用户 is_admin=1 后重试:
→ HTTP 200 {"url":"http://127.0.0.1:8158/2026/12/api-created-event-ldtH5xXyvNhd"}
# 服务端自动生成 12 位 key(ldtH5xXyvNhd),首页即刻可见,事件页 200
| 端点 | 方法 | 认证 | 说明 |
|---|---|---|---|
/api/user | GET | Bearer | 当前 token 用户信息 |
/api/add-event | POST | Bearer + 建事件权限 | 必填 name、start_date;可选 end_date/status(受 Event::$STATUSES 校验)/timezone/URL 字段(带验证规则) |
/api/add-response | POST | Bearer | 以 API 用户身份给事件写应答(照片/评论形态) |
/api/zoom/webhook | POST | 无(签名校验) | Zoom 会议联动 |
/event/{key}.json | GET | 公开 | 会议链接状态:{"meeting_url":false,"meeting_state":"none"}(实测) |
/ics/events.ics、/ics/tag/{tag}.ics、/ics/{年}/{月}/{slug}-{key}.ics | GET | 公开 | iCal 订阅面(B2 §六实测) |
/mcp | POST | — | 内置 MCP 服务端(throttle:60,1,GET 实测 405) |
五、"签到"工具链按实说明
Meetable 无二维码签到(A1 §2.4 纠偏)。现场/会后登记的 CLI-可及部分:
- RSVP 数据面:应答存
responses表(event_id+user_id+response∈{yes,if-no,if-needed,no}+approved),tinker 可直接查询统计; - 审核面:
/moderate、/event/{id}/responses(Web,管理员); - 自动化面:
POST /api/add-response以带 token 用户身份代写应答; - 导出面:
backup:all的 per-event JSON 含应答数据。
六、速查卡
# 日常
docker compose ps && docker compose logs app --tail 20
docker exec meetable-app-1 php artisan about
docker exec meetable-app-1 php artisan queue:work --stop-when-empty # 手动清队列
# 定时任务补位(B2 §八二选一)
docker exec meetable-app-1 php artisan schedule:run # 挂宿主机 cron
* * * * * docker exec meetable-app-1 php artisan schedule:run >/dev/null 2>&1
# 运维
docker exec meetable-app-1 php artisan user:passkey-link admin@e.org # 救回管理员登录
docker exec meetable-app-1 php artisan backup:all # 逻辑导出
docker exec meetable-db-1 mariadb-dump -uroot -p"$DB_ROOT_PASSWORD" meetable | gzip > backup.sql.gz
七、关联文档
- 本专栏:《Meetable 介绍与选型指南》、《Meetable Docker Compose 部署指南》、《Meetable latest 配置参数详解》
- 取证:
/opt/data/quzuo/tmp/meetable/evidence.md§7、§11