2004年7月19日

版本 0.6(变更

Bryan Ford 提出

摘要

许多应用程序创建并管理目录,包含有关存储在其他位置的内容的缓存信息,例如缓存的 Web 内容或图像或电影的缩略图大小版本。为了速度和存储效率,我们通常希望避免备份、存档或以其他不必要的方式复制此类目录,但在数据传输操作中逐一识别和排除每个此类目录非常麻烦。我提出一个极其简单的约定,通过该约定,应用程序可以可靠地“标记”其创建的任何缓存目录,以便备份系统和其他数据管理实用程序轻松识别。数据管理实用程序可以根据用户的意愿遵守或忽略这些标记。

问题

许多应用程序创建和管理某种类型的缓存目录:存储临时信息的目录,这些信息的存储可以提高应用程序的性能,但如果丢失,可以轻松从其他“主要”数据源重新生成。例如,大多数 Web 浏览器都有一个缓存目录,用于存储下载的 Internet 内容(Mozilla 通常在 $(HOME)/.mozilla 下使用名为 Cache 的目录)。在备份、同步或将用户的主目录从一台计算机传输到另一台计算机时,我们通常希望完全避免保存或传输缓存目录,因为:

  • 缓存目录的内容通常没有长期存档价值,因为它只是镜像存储在其他位置的源材料,而且通常以缩减或不完整的形式——例如,仅包含用户最近访问的网页部分,或用户浏览过的图片的缩略图版本。
  • 缓存目录可能会增长到相当大的规模——尤其是 Web 浏览器的缓存目录——可能会浪费大量备份存储空间和/或网络带宽。
  • 即使用户只是浏览或查看文件,缓存目录的内容也会频繁变化,这会使增量备份或同步软件误认为目录树中有许多频繁的“虚假更改”,从而破坏增量算法的效率。
  • 缓存目录中的文件通常命名非常隐晦(例如,基于原始源材料的名称或内容的哈希值)。在遍历用户主目录的操作中看到成千上万个这种毫无意义的名称滚动过去,最好也只是令人烦恼,而且可能会让缺乏经验的用户感到困惑或恐慌。

有许多应用程序使用缓存目录。然而,虽然一些不断发展的标准试图标准化此类目录的位置,但大多数应用程序在其不可预测的位置创建自己的缓存目录,并独立于其他应用程序进行管理。因此,即使是能够轻松识别缓存目录的有经验用户,要找出并列出备份或其他目录遍历操作的所有适当的 --exclude 选项也非常繁琐。一些应用程序(如最新版本的 KDE)将其缓存目录保存在 /tmp/var/tmp,这至少部分解决了这个问题,因为它将缓存内容完全移出了用户的主目录。但应用程序或用户可能有充分的理由不希望将这些缓存放在 /tmp/var/tmp 中:例如,这些目录可能位于具有有限空间的不同分区上,或者其中的文件可能被系统清除得过于频繁(例如,一天后或每次重启时),以至于无法让缓存有效地发挥其预期作用。

文件系统层次结构标准指定了一个系统范围的 /var/cache 目录,用于保存此类缓存信息,但该目录通常不可全局写入,因此只能由与系统一起打包或由系统管理员安装的应用程序使用。XDG 基本目录规范则建议应用程序在用户环境变量指定的位置或(如果该环境变量不存在)在用户主目录的标准子目录中创建其缓存。XDG 约定允许应用程序在没有特殊权限的情况下运行,但它无法帮助系统范围的备份或数据管理实用程序可靠地定位各个用户的缓存目录,因为每个用户可能会在其登录配置文件中以不同的方式设置环境变量。

提议的解决方案

鉴于目前在应用程序应该在哪里存储其缓存信息方面尚未达成任何完美的协议,我提出一个非常简单的约定,至少可以有效地识别此类信息。无论应用程序决定(或配置为)将其缓存目录放在何处,都应在此目录中放置一个名为以下名称的文件:

CACHEDIR.TAG

此文件必须是普通文件,而不能是例如符号链接。此外,此文件的前43 个八位字节必须由以下 ASCII 标头字符串组成:

Signature: 8a477f597d28d172789f06886806bc55

标头签名中的大小写很重要,'S' 之前不能有空格或其他字符,冒号后恰好有一个空格字符(ASCII 代码十进制 32)。标头字符串后面不必跟 LF 或 CR/LF,文件即可被识别为有效的缓存目录标记。签名中的十六进制值恰好是字符串 ".IsCacheDirectory" 的 MD5 哈希值。需要此签名标头,以避免数据管理实用程序将名为 CACHEDIR.TAG 的无关文件误认为是缓存目录标记,并(例如)导致有价值的数据不被备份。

标记文件的其余部分的内容目前未指定,但它应是 UTF-8 编码的纯文本文件,并且任何以哈希字符('#')开头的行都应被视为注释,并被读取该文件的任何软件忽略。

我们今后将把符合上述指定名称且其内容开头具有所需签名的文件称为缓存目录标记

为了方便任何碰巧直接找到并查看缓存目录标记的人,建议应用程序在文件中包含一条引用回此规范的注释。例如:

Signature: 8a477f597d28d172789f06886806bc55
# 此文件是由 (应用程序名称) 创建的缓存目录标记。
# 有关缓存目录标记的信息,请参阅:
#	http://www.brynosaurus.com/cachedir/

本规范的官方“主页”URL 可能会在某个时候从上述位置更改,如果/当本提案成为更正式的标准时,但在这种情况下,旧位置将保留适当的转发链接。

应用程序语义

给定目录中存在缓存目录标记表示该目录的全部内容(包括其下的任何和所有子目录)由可根据需要从位于其他位置的适当源材料重新生成的缓存信息组成。创建和/或使用缓存目录的应用程序应在最顶层的目录中写入一个缓存目录标记,该目录的内容代表缓存信息。例如,如果 Mozilla 创建一个名为 $(HOME)/.mozilla/default/dg8t1ih0.slt/Cache 的目录来保存从 Internet 下载的缓存内容,它就会在其中创建一个名为 $(HOME)/.mozilla/default/dg8t1ih0.slt/Cache/CACHEDIR.TAG 的缓存目录标记。只需要一个缓存目录标记即可标记整个缓存内容子目录树。如果缓存目录标记消失,应用程序还应重新生成它:例如,如果在未删除目录本身的情况下删除了缓存目录的全部内容。

如果配置为这样做,数据备份、传输或同步软件可以将目录中存在缓存目录标记解释为自动排除该目录(包括任何子目录)的命令,使其不参与备份或传输操作。我将由此类应用程序的设计者决定此“自动排除”行为是否应为默认行为,或仅在用户特别请求时采用。短期内可能需要一些保守性,但默认情况下自动排除缓存目录可能会在长期内提高效率和易用性。

为了最大限度地防止意外数据丢失,任何内置支持缓存目录标记的工具都强烈建议在确定文件确实是缓存目录标记之前,验证其找到的任何名为 CACHEDIR.TAG 的文件是否为常规文件且实际包含上述 43 字节标头。

用户友好的文件管理器和其他目录层次结构浏览软件可能也希望注意目录中存在缓存目录标记,并告知用户该目录的内容是自动管理的,如果直接“浏览”,很可能没有多大意义。

系统管理软件(如 du)可能提供一种方法来定位、汇总并报告分区上所有缓存目录的空间使用情况,帮助管理员确定文件系统上使用了多少“软”空间,如果需要,可以轻松释放。同样,实用程序可能允许管理员清除系统上的所有缓存目录,或删除超过一定“年龄”的缓存目录中的文件。

但是,系统软件不应仅基于纯粹的自动基础,定期遍历并单方面删除任意缓存目录中的“旧”文件。不同的应用程序需要能够以不同的方式管理其缓存;对一个应用程序或系统而言被视为“旧”的缓存数据对另一个应用程序而言可能不被视为“旧”(例如,如果某些数据需要很长时间才能重新生成)。未来,本标准可能会扩展,以允许应用程序在其缓存目录标记中写入其他元数据,为系统实用程序提供在全局基础上智能管理应用程序缓存所需的额外信息。但目前,引入缓存目录标记的主要目的是仅仅使避免不必要地备份或复制从一台计算机到另一台计算机的缓存数据变得容易。

安全考虑

在自动系统备份中“盲目”使用缓存目录标记可能会增加入侵者或恶意软件对系统造成的损害。用户或系统管理员可能不太可能注意到恶意插入

CACHDIR.TAG

到重要目录中,而不是直接删除该目录,例如,导致该目录的内容从定期备份中省略。为了减轻此风险,备份软件至少应告知用户由于存在缓存目录标记而被省略的目录。自动增量备份软件可能会维护一份“已批准”的缓存目录列表,并且每当出现新的缓存目录标记时,仅在获得系统管理员批准后才遵守它们。简而言之,为了在面对安全威胁时保持备份的稳健性,缓存目录标记应仅被视为提示,绝不能作为“最终决定”来决定应该和不应该备份什么。

替代方法

本节讨论在制定本提案过程中考虑的几种替代方法,以及按指定方式设计提案的理由。其格式为迷你 FAQ,解答最常见的问题。

  • 为什么不只标准化应用程序保存其缓存目录的位置? 首先,已经存在多个相互冲突的标准:例如,文件系统层次结构标准指定 /var/cacheKDE 目前使用 /var/tmp,而 XDG 基本目录规范指定使用用户可自定义的环境变量,如果该环境变量不存在,则回退到用户主目录中的 $(HOME)/.cache。即使某个标准最终“获胜”,在标准化应用程序缓存的位置和允许用户自定义之间也存在不可避免的紧张关系。XDG 规范清楚地认识到这种紧张关系并对此进行了说明,但其灵活性使得系统范围的实用程序很难或不可能可靠地定位每个用户的缓存目录,即使所有应用程序都符合 XDG 标准。

为什么不只使用某些操作系统支持的现有“无备份”或“无转储”扩展文件属性? 因为只有某些操作系统(通常只有其中的某些特定文件系统)支持这些属性。任何依赖于不可移植的操作系统功能的标记缓存目录的拟议约定,其适用性本质上有限,并且不太可能在可移植应用程序中被广泛采用。应用程序可以自由地在可用时支持特定于系统的扩展,但为了最大效用,我们确实需要一个极其简单、可移植的约定,缓存应用程序几乎可以毫不费力地采用,这就是本提案的目的。

为什么不应该所有 Web 浏览器都使用相同的缓存? 在多个 Web 浏览器或其他 Web 应用程序(所有这些应用程序可能同时运行)之间共享单个 Internet 内容缓存是一个非常有用且重要的目标——但它提出了相当大的技术挑战,这些挑战仍在解决之中。然而,即使实现了 Web 内容缓存的这种共享,许多其他应用程序仍在其磁盘上维护其他类型的缓存,在其中存储完全不同类型的数据,例如长时间运行的计算的中间结果或大型数据集的交换空间。当这些缓存具有完全不同的用途且本质上必须以不同的方式管理时,期望应用程序共享缓存是不合理的。但期望应用程序至少通过采用此处提出的简单约定使其缓存易于识别为缓存,仍然是有用的,而且现实得多。

为什么本提案仅支持缓存目录——如果应用程序只有一个文件用作缓存怎么办? 因为标记方案以这种方式要简单得多,也更容易利用,并且不会给缓存应用程序带来太大负担。如果您不担心检查缓存目录标记文件标头,那么大多数现有的、未经修改的备份/存档应用程序都可以通过一些非常简单的 shell 操作立即利用此标记约定。例如:

	find . -name CACHEDIR.TAG | sed -e 's/[/]CACHEDIR.TAG$//g' >/tmp/excludes
	tar cvf /tmp/backup.tar --exclude-from=/tmp/excludes .
	
尝试支持标记目录中的单个文件可能至少意味着需要解析文本文件并扫描文件名,从而使约定在一开始就变得更加复杂且可能脆弱。而且当涉及到影响备份哪些数据和不备份哪些数据的标准时,我们显然希望它们尽可能简单和稳健。

对于那些将所有缓存数据保存在单个文件中的现有缓存应用程序,让它们将该缓存文件向下移动一级到其自己的单独子目录中,并在该新子目录中与缓存文件一起写入缓存目录标记,应该不会过于困难。这种轻微的目录结构更改不应导致任何向后兼容性问题,因为根据定义,旧位置的任何缓存文件都是可重新生成的,并且可以直接删除或移动。而且用户不会在意,因为通常不期望他们直接看到或理解应用程序的缓存文件或目录。

结论

通过采用上述约定,在适当的地方写入缓存目录标记,创建和管理缓存目录的应用程序将使用户和系统管理员更容易识别和管理“软”存储区域,这些区域的内容对性能有用,但不需要备份或跨计算机同步。本提案有意尝试采用最简单合理且可移植的解决方案,以最大限度地提高稳健性,同时最大限度地降低采用成本,从而有望最大限度地提高最终广泛采用的机会。然而,本提案仍然为未来的增强留下了空间,在这些增强中,应用程序可能会在其缓存目录标记中包含有关其缓存目录的语义和管理的其他有用信息。

变更

  • 版本 0.6,2019年11月4日: 网页整合和重组;无实质性变更。

版本 0.5,2004年10月27日: 响应 Gregory P. Smith 指出的潜在漏洞,添加了安全考虑部分。

版本 0.4,2004年8月10日: 将缓存标记文件名从 ".IsCacheDirectory" 更改为 "CACHEDIR.TAG",以兼容旧的 14 字符 POSIX 文件系统和 8.3 字符 MS-DOS 文件系统。

版本 0.3,2004年7月29日: 建议应用程序在其标记中包含引用回此规范的注释。 建议备份/存档应用程序验证标记标头。 讨论标记文件名长度问题。

版本 0.2,2004年7月23日: 根据各种反馈充实了替代方法部分。 删除了对缩略图管理标准的引用,因为缩略图目录不完全具有纯缓存语义。

版本 0.1,2004年7月19日: 首次公开发布。

应用程序支持状态

缓存应用程序 存档/备份工具
以下应用程序已知在用户的主目录中创建和维护某种类型的缓存。

当前支持本规范的应用程序:

已收到以下开发人员的积极响应:

已与以下开发人员启动讨论:

以下存档工具支持此标记约定:

其他尚未直接对缓存标记敏感,但可以通过使用适当的选项或 shell 魔法使其敏感的存档工具:

请让我知道您所知道的其他应列入此列表的应用程序!

相关链接