您好,
最近我成了我们 Discourse Docker 镜像实例的最后一位管理员和维护者。该实例最初于 2021 年(我猜的)安装在我们的服务器上,大部分更新由他人完成。一段时间以来,可能从一开始,我们就遇到了软删除帖子中的上传文件未能被孤立和清除的问题。几天来,我一直在尝试重新排查这个问题,因为过时的文件不断堆积,浪费存储空间。我们没有使用 S3,并且有足够的存储空间来保存我们实际想要保留的上传文件。
我已经将包含上传文件的完整 Discourse 备份文件迁移到一个单独的暂存服务器上,通过按照官方 Discourse Docker 安装指南重建我们的 app.yml,然后从命令行恢复备份来进行测试。两个安装似乎都在运行,没有其他明显的问题,但上传问题依然存在。
我似乎找不到任何日志中的相关错误,Sidekiq 也在按计划运行清理作业。我在暂存版本上运行了 rake db:migrate 并进行了多次重建,尝试永久删除帖子并检查设置。在通过 rails 控制台永久删除一些帖子并尝试手动运行清理作业后,我注意到墓碑目录的大小在某个时候略有增加,而且一开始就存在一些文件,所以这个机制在某些情况下肯定是在工作的,对吧?从大小的微小增加来看,几乎所有过时的文件仍然没有被检测为孤立文件。
当前相关的管理面板设置如下。我能否将最后几项设置为 0 以在测试中有效地跳过宽限期?
清理上传 = true
孤立上传清理宽限期(小时) = 1
删除的上传清除宽限期(天) = 1
如何有效地排查此问题? 我熟悉命令行,但我的数据库技能很基础,所以我很想得到一些建议,避免在不知道自己在寻找什么的情况下,逐一检查所有可能的服务器设置细节。
我一直在绝望地搜索和阅读本论坛上类似的案例,但只有少数几个,而且那些帖子似乎要么陷入了死胡同,要么提供了针对单个文件的手动解决方案,因此不适合此用例。
如果需要更多详细信息,请随时提出,我将尽力彻底解决这个问题。
3 个赞
响应迅速,不胜感激!
在尝试解决此问题的过程中,我已对这些主题以及其中链接的几个其他主题相当熟悉,但遗憾的是,它们并未为这个问题提供任何确切的解决方案。
昨天,我在暂存服务器上运行了针对 9 天前删除的主题和帖子修改后的命令:
在此之后,我注意到墓碑目录内容的大小略有增加,并且由于宽限期,我仍在监控情况,同时还在想将相关设置更改为零小时/天是否可以绕过测试期间的等待时间。
早些时候,我在原始服务器上尝试从最新的帖子修订中删除上传文件,但在宽限期后这些文件仍然可用。
此时,我个人非常乐意找到任何有效的手动解决方案来永久删除单个主题及其帖子和上传文件(未在其他地方引用),但这对于其他运行 Discourse 的人来说可能是一个大问题,因为他们自然会认为管理员面板中的清理设置会如所述那样有效,但不一定会注意到它是否无效,并最终导致本应永久删除但实际上仍保留在文件系统中的敏感上传文件。幸运的是,我们遇到的问题仅涉及存储空间浪费,但对其他人来说可能会更糟。
两个月前还有另一个类似的提及:
那么,有什么技巧可以帮助我们弄清楚这是我们配置错误还是实际的错误?否则,我们对 Discourse 非常满意,我非常有动力解决这个问题并帮助他人。
1 个赞
这纯属猜测,但从快速浏览 post、post_upload 和 upload 模型来看,您或许可以通过以下方式找出是否存在孤立的上传(数据库对象):
Upload.find_by_sql("select * from uploads where id in (select upload_id from post_uploads where post_id not in (select id from posts))")
我还没有测试过,所以不确定它是否能正确找到孤立的上传,甚至是否能无错误地执行。如果它不能按原样工作,而其他人可能能够使其工作,并且也只是为了其他感兴趣的人,我将分解其意图。
Upload.find_by_sql() 返回一个 Upload 对象集合,这些对象与提供的 SQL 查询匹配。
(select id from posts) 获取所有现有帖子的 ID。
(select upload_id from post_uploads where post_id not in () 获取所有不存在帖子的 post_uploads 的 ID。
select * from uploads where id in () 获取与这些 post_uploads ID 匹配的所有上传。
不过,这只是一个可以调查的途径,不幸的是,我对上传系统不够了解,无法提供太多其他帮助,只能说上述方法不考虑所有情况。例如,编辑过的帖子而不是删除的帖子就是一个明显的例子。
还有其他类型的上传未被考虑在内,例如用户上传,我假设这是指上传个人资料图片之类的内容。
插件也可以创建并保留上传,我不知道如果插件被删除会发生什么。我认为插件数据在插件被删除后仍然保留在数据库中,这可能意味着该插件创建的任何上传在这种情况下永远不会被删除。
4 个赞
感谢您的回复!
查询可以工作,但它只列出了两个上传及其详细信息。应该有数百甚至数千个符合孤立文件标准的上传,其中大部分是用户在正常发帖时上传的图片文件。
我们目前只使用官方插件:
hooks:
after_code:
- exec:
cd: $home/plugins
cmd:
- git clone https://github.com/discourse/docker_manager.git
- git clone https://github.com/discourse/discourse-chat-integration.git
- git clone https://github.com/discourse/discourse-prometheus.git
- git clone https://github.com/discourse/discourse-bbcode-color
- git clone https://github.com/discourse/discourse-data-explorer
在我最初安装之后不久,上传过程似乎经历了一次大修,我想知道这是否与我们的情况有关:A new era for file uploads in Discourse
暂存服务器的宽限期应该已经过了,但我没有看到上传目录大小有任何变化,测试文件仍然可用。接下来我应该检查什么?这是否可能由某些错误的文件系统权限引起,是否有简单的方法可以检查?我快没主意了,其他一切运行正常,这是我们目前唯一的问题。
正在浏览类似的主题以收集可能匹配的未解决案例,这里有一个很好的例子说明这些情况甚至可能因用户上传未被孤立和永久删除而导致法律问题:
另一个类似的情况,可以追溯到 2016 年:
这些情况为滥用甚至针对上传非法内容的攻击创造了巨大的空间,即使管理员认为它们会被永久删除,但实际上可能不会。当然,可以直接从文件系统中手动删除单个文件,但我认为用户不应该为了这种基本需求而被强迫走这条路,特别是当有一个 GUI 设置指示自动清理过程,并且版主通常无法直接访问服务器时。此外,当大量文件散布在不同的已删除主题中时,手动删除并不实用。
这里有足够的理由进行实际的错误报告吗? 我仍然不排除我们这边可能存在配置错误,但我对缺乏错误消息感到困惑,而且其他一切似乎都运行正常。我花了越来越多的时间进行故障排除和测试,在此过程中获得了关于 Discourse 及其组件的更多知识,因此我认为在一些指导下,我应该能够帮助弄清楚是否存在某些极端情况触发了这种奇怪的行为。我希望现在可以 ping @zogstrip?
作为临时解决方案,是否可以将所有上传的文件手动移至墓碑目录,并使用上传恢复方法仅将非孤立文件恢复到其正确的目录?我今天实际上尝试过这样做,但 rake uploads:recover_from_tombstone 没有恢复任何文件。这是否可能指向上传数据库条目存在更大的问题?
groove6j
(kilometrs)
7
您好。我遇到了相同或类似的问题,无法弄清楚为什么文件无法删除。还有其他人仍然遇到此问题吗?
我运行了一些 SQL 查询,发现“卡住”的上传引用似乎都是 Drafts,但我检查了我和其他用户的 Drafts,但没有。Drafts 表是空的。
孤立文件清理已启用,并且设置已设置为尽快删除孤立文件。
我附上了一个 SQL 查询。
SELECT
uploads.original_filename,
ROUND(uploads.filesize / 1000000.0, 2) AS size_in_mb,
uploads.extension,
uploads.created_at,
uploads.url,
upload_references.upload_id,
upload_references.target_id,
upload_references.target_type,
upload_references.created_at,
upload_references.updated_at
FROM upload_references
JOIN uploads ON uploads.id = upload_references.upload_id
ORDER BY uploads.filesize DESC
LIMIT 250
sql.csv (46.1 KB)
自从我安装论坛以来,这种情况就一直存在。即使没有安装自定义主题或插件。
甚至我上传过几次的旧论坛徽标(有史以来上传的第一个文件)仍然被引用为 Draft,并且仍然在 uploads 文件夹中。 
理论上,我可以过滤所有上传引用,按 target_type 过滤 Drafts,然后从数据库中删除……然后让 sidekiq 任务处理清理(我说得对吗?)
但我使用的是自托管实例,而且我对 Discourse 相当陌生,所以最好在这里问一下……
这将是一个变通方法,但仍然有一个问题——为什么会发生这种情况?
希望有人能提出一些建议,我的磁盘空间正在呈指数级增长 
1 个赞
是的,我们仍然遇到这个问题。
我真的很想以某种方式解决它,我们的论坛会收到很多上传,但只有一小部分需要长期保存,所以浪费了很多磁盘空间。欢迎任何有关故障排除的建议。
如果可行,我对这个临时解决方案感兴趣。
groove6j
(kilometrs)
9
我两周前安装了论坛,从一开始就出现了这个问题。看起来像是一个 bug。
你能运行相同的 SQL 查询并检查是否有大量卡住的“草稿”引用吗?很容易发现,我有几十个,但在草稿表中只有 2 或 3 个真正的草稿。看起来它们在编辑后不会被删除(不再是草稿,但每次编辑帖子时,数据库中都会留下引用)。
我需要弄清楚如何从数据库中删除引用条目,并首先删除一个文件的引用,然后检查清理任务是否正常工作。
我不知道这样做有多安全,但这些无数的草稿条目对我来说似乎是错误的。
我可以向工作人员/开发人员提供日志,我只是 Discourse 的新手,不知道哪些日志文件会有帮助。
编辑:
我正在尝试理解数据库结构,并且可以删除这些上传条目而不产生其他问题(我不想错过任何重要的数据库关系)。另外,我不明白 draft_sequences 到底是什么。
但我必须将我的生产论坛复制到一个本地虚拟机,只有那样我才能测试……
另一个相关话题,我发帖了,因为我不知道这个话题。
我认为唯一真正自动删除图像的方法是在删除帖子之前手动将其从帖子中编辑掉。但我不确定这是否有效。我使用的清理设置与您完全相同(但使用 S3 兼容存储),并且我也可以确认,如果包含图像的唯一帖子(同一图像可以包含在多个帖子中,推测头像和用户横幅也是如此)被删除,图像永远不会被清理。
我使用此解决方案来搜索图像是否在其他帖子中使用,该解决方案由 @RGJ 提供
如果可以自动完成,那将是极好的。特别是由于 Discourse 以智能方式处理图像,通过防止在许多帖子使用同一图像时创建重复文件。另一方面,手动删除大量使用的单个图像非常繁琐。
我曾有过某人通过多个帐户垃圾邮件发送需要紧急删除的内容,而我试图处理并确保其完全删除(所有原始文件、优化文件、CDN 缓存、帖子、头像、用户横幅等)非常令人紧张。
我提出了这个功能建议,因为我认为它会非常有帮助。如果实现了这个功能,以及自动清理已删除帖子中包含的内容,我认为所有情况都将得到涵盖,并且可以在没有 SSH 访问权限的情况下进行处理。
1 个赞