在尝试恢复备份时(针对多站点环境,但这似乎并不重要,详见下文),会出现以下情况:
正在迁移数据库...
异常: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 期间跳过图片优化,但我尝试时并未奏效。