Files
2026-10-22 11:02:57 +08:00
..
2026-10-22 11:02:57 +08:00

IM 聊天同步缓存权限

线上应用路径为 /www/wwwroot/zyt/server,PHP 为 /www/server/php/82/bin/php,PHP-FPM 工作进程和应用 worker 使用 www。

故障原因

网页分页同步、CLI 聊天补拉、内置定时任务共用 runtime/cache/la。root 直接执行 php think 会生成 root 所有的 0755 子目录或 0644 文件,随后 www 的 file_put_contents 报 Permission denied。2026-10-20 现场确认 256 个散列子目录中有 76 个归 root 所有。

修复与防复发

先备份现有任务定义和生成脚本,把此应用中以 root 运行的 PHP 命令改为:

cd /www/wwwroot/zyt/server
/usr/sbin/runuser -u www -- /www/server/php/82/bin/php think crontab

sync_im_chat_archive 及其他同项目命令同样使用该前缀,保留原参数、周期和 flock。宝塔计划任务必须同时修改保存的脚本内容与当前生成的 /www/server/cron/<任务标识>;只修改生成脚本会在面板重新保存时丢失修复。已有 www 包装的任务不需要重复降权。

部署、迁移、预热、清理等手动 PHP 命令也必须使用 www。Supervisor 的本应用 worker 同样设置 user=www。

确认路径没有重定向后,仅修复已有缓存树的 root 属主,保留缓存内容和权限:

cache_path=/www/wwwroot/zyt/server/runtime/cache
test "$(readlink -f -- "$cache_path")" = "$cache_path" || exit 1
chown -hR -P --from=root www:www "$cache_path"

不清空缓存或聊天归档,不对整个 runtime 递归 chmod;其中包含私有文件。

验证

  1. 用 www 通过 ThinkPHP Cache 写入、读取、覆盖、删除专用探针键,确保遍历全部 256 个散列目录。
  2. 在诊单 13780 的聊天记录中完成一次分页同步,并再次触发同步验证检查点可覆盖。
  3. 等待原有调度至少运行一轮,检查 PHP 任务身份与探针、检查点文件属主,确认没有重新产生 root 缓存。
  4. 检查宝塔保存的任务正文与生成脚本均已更新;使用备份文件可恢复原始任务定义。

本次是线上运行用户和文件归属修复,无需更改聊天同步业务代码。

2026-10-20 现场执行记录

  • 原任务备份:服务器 /root/zyt-cache-permissions-20261020T104145/,包含任务原正文、生成脚本及 root crontab。
  • 已修正 14 条宝塔任务、17 条 PHP 命令,任务正文与生成脚本逐项比对一致;已有 www 包装的任务保持原样。
  • 已停止仍在运行的旧 root 调度进程,原有 cron 自动启动的新调度进程为 www;分钟通知任务连续正常完成。
  • www 通过实际 ThinkPHP File 驱动遍历 256 个散列分区,创建、读取、覆盖、删除及文件属主检查全部通过。
  • 诊单 13780 的全账号分页流程连续推进 66 步、完成 32 个会话,未出现权限错误;随后停止该诊断流程,改为对截图中关联账号 213 的会话完成两轮完整同步。两轮均无错误,归档读取返回 27 条记录;旧记录没有重复插入。
  • 同步验证在服务器以 www 调用网页使用的 syncImChatArchiveStep() 和归档读取逻辑完成。所给 admin1 不是业务后台账号,未进行已登录网页接口复测。
  • 存量修复于 2026-10-20 10:58(北京时间)全部完成:256 个分区,共检查 2,590,008 项缓存文件与目录,错误数为 0;扫描期间 2 项缓存由正常业务过期移除。修复保留缓存内容和原权限,仅恢复 root 所有条目的归属。
  • 最终复核通过:14 条任务、17 条 PHP 命令与持久化配置一致;256 个目录和每目录抽样文件均为 www;调度进程为 www;256 个缓存分区读写、覆盖、删除通过,诊单 13780 / 关联账号 213 的同步在 3 步内完成且无错误,归档仍为 27 条。结构化证据见 验收记录。