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

**URL:** https://meta.discourse.org/t/bug-when-restoring-svg-files-from-backup/143120
**Category:** Bug
**Created:** [2020年三月2日 19:18 UTC](https://meta.discourse.org/t/bug-when-restoring-svg-files-from-backup/143120 "2020-03-02T19:18:42Z")
**Posts on this page:** 6
**Page:** 1

<div class="post-metadata">

### Author: ![RGJ](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/rgj/32/523185_2.png) [@RGJ](https://meta.discourse.org/u/RGJ)
#### Post date: [2020年三月2日 19:18 UTC](https://meta.discourse.org/t/bug-when-restoring-svg-files-from-backup/143120/1 "2020-03-02T19:18:42Z")

</div>

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

```
正在迁移数据库...
异常：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 上传的代码走了一条不同的路径，导致彻底失败 [具体路径如下](https://github.com/discourse/discourse/blob/stable/app/models/optimized_image.rb#L86-L93)。对于其他类型的上传，似乎只是静默失败。

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

---

<div class="post-metadata">

### Author: ![codinghorror](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/codinghorror/32/110067_2.png) [@codinghorror](https://meta.discourse.org/u/codinghorror)
#### Post date: [2020年三月3日 02:41 UTC](https://meta.discourse.org/t/bug-when-restoring-svg-files-from-backup/143120/2 "2020-03-03T02:41:48Z")

</div>

@sam，谁应该查看这个？

---

<div class="post-metadata">

### Author: ![sam](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/sam/32/102149_2.png) [@sam](https://meta.discourse.org/u/sam)
#### Post date: [2020年三月3日 02:53 UTC](https://meta.discourse.org/t/bug-when-restoring-svg-files-from-backup/143120/3 "2020-03-03T02:53:39Z")

</div>

看起来相当直接：

> <https://github.com/discourse/discourse/blob/0388653a4d7d422a1525649a155182446da34405/lib/backup_restore/restorer.rb#L49-L58>

以及

> <https://github.com/discourse/discourse/blob/0388653a4d7d422a1525649a155182446da34405/lib/backup_restore/database_restorer.rb#L19-L31>

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

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

---

<div class="post-metadata">

### Author: ![RGJ](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/rgj/32/523185_2.png) [@RGJ](https://meta.discourse.org/u/RGJ)
#### Post date: [2020年三月3日 16:55 UTC](https://meta.discourse.org/t/bug-when-restoring-svg-files-from-backup/143120/5 "2020-03-03T16:55:25Z")

</div>

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

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

顺便一提，我刚刚发现 `SKIP_POST_DEPLOYMENT_MIGRATIONS` 被显式地[重置](https://github.com/discourse/discourse/blob/f216c6d60b8740a66e04b05c3e5c865e8a4b4f91/lib/backup_restore/database_restorer.rb#L137)，这就是为什么它作为变通方法不起作用的原因。

---

<div class="post-metadata">

### Author: ![gerhard](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/gerhard/32/119479_2.png) [@gerhard](https://meta.discourse.org/u/gerhard)
#### Post date: [2020年三月4日 16:01 UTC](https://meta.discourse.org/t/bug-when-restoring-svg-files-from-backup/143120/6 "2020-03-04T16:01:04Z")

</div>

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

> <https://github.com/discourse/discourse/commit/8fa8bab9ff361bfa36592a6e32cfb96a4fc38d06>
>
> Uploads are extracted after the DB migration, so this could lead to a failure du…ring the restore. Site icons get optimized after extracting uploads.

---

<div class="post-metadata">

### Author: ![gerhard](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/gerhard/32/119479_2.png) [@gerhard](https://meta.discourse.org/u/gerhard)
#### Post date: [2020年三月4日 16:01 UTC](https://meta.discourse.org/t/bug-when-restoring-svg-files-from-backup/143120/7 "2020-03-04T16:01:09Z")

</div>


