如何创建一个忽略其内容时间戳的tar文件?

45

有没有一种方法可以创建一个.tar文件,省略其文件/目录的atime/ctime/mtime值?

为什么要这样做?

我们在构建过程中有一个步骤,生成一个包含构件的目录,并将其打包成tar文件。我们期望该构建步骤是幂等的--给定相同的输入,每次它都会产生完全相同的文件/输出。

理想情况下,我们也希望该步骤在干净的构建之间是按位幂等的,以便我们可以使用连续构建的哈希来检查是否有任何更改。但由于tar文件包括每个条目的时间戳(atime/ctime/mtime),因此由该构建步骤创建的tar文件从未与上一次运行完全相同,即使存档中每个文件的内容都是按位相同的。

有没有一种生成省略其条目时间戳的tar文件的方法,以便生成存档的步骤可以成为按位幂等的?(我们希望利用tar保留的其他文件元数据,例如文件模式位和符号链接。)


你有没有找到这个问题的完整答案?我也想做同样的事情,在这里提出了一个问题:https://stackoverflow.com/questions/45734702/tar-preserving-only-file-names-contents-and-executable-bit?noredirect=1#comment78427625_45734702 我还想确保用户、组和权限不被存储。还有其他需要注意的地方吗? - Tom Ellis
@TomEllis,如果您想要精确控制存储哪些权限和不存储哪些权限,我建议使用Python的tarfile模块构建自定义内容。 - Charles Duffy
1
看一下这个:https://reproducible-builds.org/docs/archives/#full-example - undefined
3个回答

36
为了拥有真正幂等的 tar,mtime是一个好的步骤,但不足够。您还需要设置排序顺序、所有者和组(以及它们的映射)以及适当的时区来维护 mtime(否则在 Mac 和 Linux 之间也可能会出现问题)。
我最终得到了:
tar --sort=name --owner=root:0 --group=root:0 --mtime='UTC 2019-01-01' ... | gzip -n

1
注意:此解决方案需要 GNU tar 1.28 或更高版本。 - Mickalot
你是否也需要强制执行一个明确定义的排序顺序,例如通过设置环境变量 LC_ALL=c - Mickalot
2
@Mickalot,你在问题中明确地说过:我们想利用tar保留的其他文件元数据,要求回答者限制自己只讨论时间戳。将接受位移动到不遵守该规范的答案似乎是在改变目标。 - Charles Duffy
8
此问题涉及按位幂等性,因此我认为答案应包括任何有助于实现该目标的内容,包括文件所有权和排序顺序。 - Jesse Glick
@Mickalot,那你真的想要tar文件吗?如果你不想要元数据,那么你可以考虑阅读这个帖子https://unix.stackexchange.com/a/349948或者给@Charles Duffy采纳答案。 - undefined
@Et7f3XIV:查尔斯·达菲的回答是对我所问的问题的精彩回应。这个回答改进了我的问题,并(正确地)推测出了我应该问的问题。它们都是很好的答案,我希望我能有两个“被接受的答案”来奖励。 - undefined

28

GNU tar有一个--mtime参数,可以用来将固定日期存储在归档中,而不是文件的实际修改时间:

tar --mtime='1970-01-01' input ...

使用gzip压缩tar包时,还需要指定-n选项以防止存储tar归档的名称和时间戳:

tar --mtime='1970-01-01' input ... | gzip -n >input.tar.gz

在 macOS 上如何完成这个操作?我找不到 --mtime - mljrg
9
在 macOS 上,标准的 tar 命令是基于 BSD 的,而 BSD 版本的 tar 与 GNU 版本的 tar 是不同的。如果你想安装 GNU 版本的 tar,可以使用 Homebrew 来安装,命令为 brew install gnu-tar,这样就能使用 GNU 版本的 tar,名称为 gtar - Mickalot
@Mickalot 谢谢! - mljrg
1
--mtime='@0'是更短且似乎具有相同功能(使用这两个选项制作的tar包匹配MD5校验和)。 - leetbacoon

-6

我们可以创建一个不带时间戳的 tar 文件。

1)创建无压缩和时间戳的 tar 文件

tar -cf file_name.tar file_name

2) 创建带压缩且无时间戳的tar文件

tar -cf file_name | gzip -n > file_name.tar.gz

3) 另一种方法

GZIP=-n tar -czf file_name.tar.gz file_name

注意:'-n' 不会添加时间戳和名称。
4)提取tar文件。
tar -xf file_name.tar and tar -xzf file_name.tar.gz

你可以像这样验证

file file_name.tar or file_name.tar.gz
output = file_name.tar.gz: gzip compressed data, from Unix

2
tar -c 在归档中包含修改时间戳。 - Charles Duffy

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接