# 迁移到 s3 失败 - 但只有检查失败

**URL:** <https://meta.discourse.org/t/migrate-to-s3-failed-but-only-check-fails/394193>\
**Category:** Bug\
**Created:** [2026年一月23日 15:33 UTC](https://meta.discourse.org/t/migrate-to-s3-failed-but-only-check-fails/394193 "2026-01-23T15:33:13Z")\
**Posts on this page:** 1\
**Showing post:** 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:** [2026年一月23日 15:33 UTC](https://meta.discourse.org/t/migrate-to-s3-failed-but-only-check-fails/394193/1 "2026-01-23T15:33:13Z")

</div>

多年来，我们在迁移到 S3 的过程中看到了许多问题，包括恢复备份时的隐式迁移。

```plaintext
EXCEPTION: 8 个帖子未重新映射到新的 S3 上传 URL。 数据库 'default' 的 S3 迁移失败。

```

许多例子中的一些：

- [False positives on "posts are not remapped to new S3 upload URL"](https://meta.discourse.org/t/false-positives-on-posts-are-not-remapped-to-new-s3-upload-url/370290/)
- [Restore process cancelled at migrating uploads to S3 step](https://meta.discourse.org/t/restore-process-cancelled-at-migrating-uploads-to-s3-step/123233/)
- [Restore to New Host](https://meta.discourse.org/t/restore-to-new-host/219515/)

今天，我遇到了另一个这样的问题，因为是星期五，我决定深入研究一下，而不是简单地注释掉检查。

所以我们有以下情况：

- 我们在多站点上
- 假设 `dbname` 是此示例的数据库名称
- 我们设置了 `S3_CDN_URL`
- 我们没有设置 `CDN_URL`

这是在 `/lib/file_store/to_s3_migration.rb` 中发生的情况

首先[这里](https://github.com/discourse/discourse/blob/a96ebac814c21c359200e170daa421007368da8b/lib/file_store/to_s3_migration.rb#L190)决定前缀

`prefix = @migrate_to_multisite ? "uploads/#{@current_db}/original/" : "original/"`

然后文件上传到 s3，[然后](https://github.com/discourse/discourse/blob/a96ebac814c21c359200e170daa421007368da8b/lib/file_store/to_s3_migration.rb#L288-L326)进行重新映射，这基本上是这个以及一些变体

```plaintext
        from = "/uploads/#{@current_db}/original/"
        to = "#{SiteSetting.Upload.s3_base_url}/#{prefix}"

```

所以在多站点中，这将重新映射

- 从 `/uploads/dbname/original/`
- 到 `https://bucket-location-url.com/uploads/dbname/original/`

然后[最后](https://github.com/discourse/discourse/blob/a96ebac814c21c359200e170daa421007368da8b/lib/file_store/to_s3_migration.rb#L77-L78)进行检查

```plaintext
      cdn_path = SiteSetting.cdn_path("/uploads/#{@current_db}/original").sub(/https?:/, "")
      count = Post.where("cooked LIKE '%#{cdn_path}%'").count
      if count > 0
        error_message = "#{count} posts are not remapped to new S3 upload URL. #{failure_message}"
        raise_or_log(error_message, should_raise)
        success = false
      end

```

现在 `SiteSetting.cdn_path` 来自 `lib/global_path.rb` 并且如下所示

```plaintext
  def cdn_path(p)
    GlobalSetting.cdn_url.blank? ? p : "#{GlobalSetting.cdn_url}#{path(p)}"
  end

```

所以，如果我们有一个 S3 CDN 但没有常规的 CDN，那么 `SiteSetting.cdn_path("/uploads/#{@current_db}/original")` 将是 `/uploads/dbname/original`

并且，根据我们的重新映射，新的路径是 `https://bucket-location-url.com/uploads/dbname/original/`

这意味着

1. `cdn_path` 是新目标路径的子字符串
2. 因此 `Post.where("cooked LIKE '%#{cdn_path}%'").count` 将始终找到帖子
3. 它会虚报警报并退出 😱 😱 😱

---

_[View the full topic](https://meta.discourse.org/t/migrate-to-s3-failed-but-only-check-fails/394193)._
