从备份恢复 SVG 文件时出现错误

在尝试恢复备份时(针对多站点环境,但这似乎并不重要,详见下文),会出现以下情况:

正在迁移数据库...
异常:lib/discourse.rb:57:in `exec': 数据库迁移失败。
rake aborted!
Errno::ENOENT: 没有那个文件或目录 @ rb_sysopen - /var/www/discourse/public/uploads/default/original/2X/7/7be997f9f48c034ddf5d4eb95d2ea7416f010241.svg
/var/www/discourse/app/models/optimized_image.rb:87:in `block in create_for'
/var/www/discourse/app/models/optimized_image.rb:24:in `block (2 levels) in lock'
/var/www/discourse/lib/distributed_mutex.rb:33:in `block in synchronize'
/var/www/discourse/lib/distributed_mutex.rb:29:in `synchronize'
/var/www/discourse/lib/distributed_mutex.rb:29:in `synchronize'
/var/www/discourse/lib/distributed_mutex.rb:14:in `synchronize'
/var/www/discourse/app/models/optimized_image.rb:23:in `block in lock'
/var/www/discourse/lib/distributed_mutex.rb:33:in `block in synchronize'
/var/www/discourse/lib/distributed_mutex.rb:29:in `synchronize'
/var/www/discourse/lib/distributed_mutex.rb:29:in `synchronize'
/var/www/discourse/lib/distributed_mutex.rb:14:in `synchronize'
/var/www/discourse/app/models/optimized_image.rb:22:in `lock'
/var/www/discourse/app/models/optimized_image.rb:59:in `create_for'
/var/www/discourse/lib/site_icon_manager.rb:28:in `block in ensure_optimized!'
/var/www/discourse/lib/site_icon_manager.rb:24:in `each'
/var/www/discourse/lib/site_icon_manager.rb:24:in `ensure_optimized!'
/var/www/discourse/lib/tasks/db.rake:83:in `block in <top (required)>'
/var/www/discourse/vendor/bundle/ruby/2.6.0/gems/rake-13.0.1/exe/rake:27:in `<top (required)>'
/var/www/discourse/vendor/bundle/ruby/2.6.0/bin/ruby_executable_hooks:24:in `eval'
/var/www/discourse/vendor/bundle/ruby/2.6.0/bin/ruby_executable_hooks:24:in `<main>'
任务:TOP => db:migrate

起初我以为这纯粹是多站点的问题,但在非多站点环境中也会出现同样的失败。

有趣的是,当时甚至还没有解压上传文件(编辑:指在那个时间点)。不过该特定上传文件确实包含在归档中。

tar tvf public/backups/default/redacted-forum-2020-03-02-165725-v20190130013015.tar.gz |grep 7be997f9f48c034ddf5d4eb95d2ea7416f010241
-rw-r--r-- daemon/daemon     3074 2019-05-27 08:21 uploads/default/original/2X/7/7be997f9f48c034ddf5d4eb95d2ea7416f010241.svg

原始数据库转储版本为 v20190130013015

随后我手动解压了上传文件(到 default 目录),然后再次运行恢复操作,这次成功了。

接着我发现了问题所在……上传文件是在 db:migrate 之后才被解压的,但 db:migrate 却运行了 SiteIconManager.ensure_optimized!,这要求文件必须已经存在……

因此存在两个问题:

  • SiteIconManager.ensure_optimized! 在图片尚未解压时就运行了;(实际上它运行了两次——在上传文件解压后又运行了一次)
  • 它期望文件位于 default 目录中,因为重映射尚未执行。

在这个特定案例中,由于 SVG 上传的代码走了一条不同的路径,导致彻底失败 具体路径如下。对于其他类型的上传,似乎只是静默失败。

顺便提一下,查看代码后发现,似乎可以通过设置 SKIP_POST_DEPLOYMENT_MIGRATIONS=1 来规避此问题,因为该设置会在 db:migrate 期间跳过图片优化,但我尝试时并未奏效。

6 个赞

@sam,谁应该查看这个?

1 个赞

看起来相当直接:

以及

上一次有人尝试调整此流程的是 @gerhard

@RGJ,如果您想加快这里的诊断速度,或许可以创建一个空数据库,其中仅包含一个导致恢复失败的 SVG 文件,这将大大方便我们进行测试。

7 个赞

我给您发了一条私信,里面有一个尽可能精简的备份文件,但该文件无法恢复。

触发此错误需要“一个”favicon 或 manifest 中的“小型”svg 文件。

顺便一提,我刚刚发现 SKIP_POST_DEPLOYMENT_MIGRATIONS 被显式地重置,这就是为什么它作为变通方法不起作用的原因。

5 个赞

感谢您报告问题并提供示例文件。该问题已修复。

6 个赞