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)

MeetableMeetable自托管DockerLaravel命令行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 passkeyheadless 管理员登录入口
backup:allBack up all events into a folder on disk事件/用户 JSON 导出
webmention:refreshFetch all webmentions again and re-parsewebmention 抓取修复
event:notifySend notifications for upcoming events会前提醒(scheduler 任务)
discord:notify / discord:sync-eventsDiscord 频道预告 / 服务器事件列表同步Discord 集成运维
recurring:scheduleCreate events from the scheduled recurring events周期事件实例生成(每日 0 点)
user:fetch_details {url?}拉取用户 h-card 资料资料修复
migrate:settingsMigrate 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/userGETBearer当前 token 用户信息
/api/add-eventPOSTBearer + 建事件权限必填 name、start_date;可选 end_date/status(受 Event::$STATUSES 校验)/timezone/URL 字段(带验证规则)
/api/add-responsePOSTBearer以 API 用户身份给事件写应答(照片/评论形态)
/api/zoom/webhookPOST无(签名校验)Zoom 会议联动
/event/{key}.jsonGET公开会议链接状态:{"meeting_url":false,"meeting_state":"none"}(实测)
/ics/events.ics、/ics/tag/{tag}.ics、/ics/{年}/{月}/{slug}-{key}.icsGET公开iCal 订阅面(B2 §六实测)
/mcpPOST—内置 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 latest 常用 CLI 命令与工具详解 - Quzuo