【问题标题】:How can I set file creation times in ZFS?如何在 ZFS 中设置文件创建时间?
【发布时间】:2015-07-06 12:47:19
【问题描述】:

我刚刚有一个运行 ZFS 的 NAS,我想在将文件传输到其中时保留创建时间。 linux/ext4(数据现在所在的位置)和 zfs 都存储创建时间或出生时间。在 zfs 的情况下,它甚至由 stat 命令报告。但我无法弄清楚如何设置文件的创建时间,以便它反映原始文件系统中的创建时间。与 ext4->ext4 传输不同,我可以为 debugfs 提供一个脚本来设置文件创建时间。

ZFS 有没有类似 debugfs 的工具?

附言。为了更好地解释:

  • 我有一个连接到 Ubuntu 14.04 笔记本电脑的 USB 驱动器。它拥有一个文件系统,我关心各个文件的创建日期(出生日期)。我经常使用基于 debugfs 的脚本查阅这些创建时间戳,该脚本将其报告为 crtime。

  • 我想将数据移动到运行 ZFS 的 NAS 盒中,但我知道的方法(scp -p -r、rsync -a 和 tar,以及我尝试过的其他方法)保留了修改时间,但不是创建时间。

  • 如果我要迁移到另一个 ext4 文件系统,我会使用出色的工具 debugfs 来解决问题。具体来说,我可以在源 fs(文件系统)上列出 (filename, crtime) 对,然后在目标 fs 上使用debugfs -w 来读取具有以下形式的行的脚本

    set_inode_field filename crtime <value>

我已经对此进行了测试,并且效果很好。

  • 但是我的目标 fs 不是 ext4 而是 ZFS,虽然 debugfs 在目标机器上运行,但它在那里完全没用。它甚至不识别fs。另一个可以让您通过直接编辑 inode 来更改时间戳的调试工具是 fsdb;它也在目标机器上运行,但我似乎无法让它识别 ZFS 文件系统。

  • 卖给我 NAS 盒子的人告诉我,debugfs 和 fsdb 不适用于 ZFS 文件系统,但他们还没有找到等效的。所以,经过多次谷歌搜索和尝试,我终于决定今天在这里发布一个问题,希望有人能给出答案。

我很惊讶这会变得多么困难。从档案的角度来看,如何复制数据集以使所有时间戳都相同的问题似乎很自然。

【问题讨论】:

  • 不明白为什么这不属于服务器故障。
  • 嗨,杰,谢谢。您是否建议我将问题移至服务器故障?如果是这样,我是否应该在此处等待赏金期用完并删除问题并将其发布到 serverfault 上?我不是专业的系统管理员,我只是管理家里的 5 个 linux 机器,所以发布问题对我来说是一个新领域。
  • 如果您现在可以删除它,我建议您这样做。 (我希望你会吸引反对票而不是接近投票,因为人们不能在有赏金时投票关闭。)然后尝试在那里发帖;您的问题似乎表述得很好,主题应该与他们的兴趣相关。
  • 谢谢。所以你说反对票是因为这个问题是题外话。我不会从许多其他问题中猜到。在其他 SE 网站上,我属于对问题投反对票的人会发表评论以解释原因,除非该问题完全是垃圾。感谢您的帮助。
  • 如果解决方案涉及脚本,那么它的价值,stackoverflow 仍然是发布它的合适地方。 +1

标签: filesystems timestamp freebsd inode zfs


【解决方案1】:

确实,fsdbdebugfs 都不适合与 ZFS 一起使用。您可能需要做的是找到一种存档格式,该格式将保留可能已经为文件服务器上的文件设置的 crtime 字段。如果您的系统有 pax 的版本或其他归档工具,它可能能够做到这一点(cf.-pepax 的“保留一切”标志,它似乎在当前版本保留“一切” - 它不保留crtime/birth_time)。您可能会更成功地找到一个“crtime 感知”的归档应用程序,而不是尝试通过使用可能是基本工具的基于 ZFS 的 FreeBSD 系统来设置创建时间。

您可以在基于 OpenSolaris 的系统上找到更高级的工具,例如 IllumosSmartOS例如 mdb)。是否可以将您的数据传输到其中一个平台上的 ZFS 数据集,然后将他们拥有的工具与dtrace 结合起来以重写crtime 字段更多的是一个理论问题。如果它有效,那么您可以将池及其数据集导出到 FreeBSD - 导出池似乎确实保留了 crtime 时间戳。如果您能够在将 ext4 文件系统转储到同一主机上的 ZFSonLinux 数据集时保留crtimenb:我有未对此进行测试)然后您可以使用 zfs send 将整个文件系统传输到您的 NAS。

core utils bug report 可能会揭示 Linux 上用户和操作系统级工具的状态。可以说,inode 的文件系统级别 crtime 字段应该很难更改。虽然 ZFS 在 FreeBSD“支持”crtime,但 FreeBSD 上低级文件系统调试工具的状态可能跟不上早期版本的步伐(cfzdb 手册页)。您确定要“设置”(或重置)inode 创建时间吗?或者您想在已经支持它们的系统上设置它们后保留它们?

在 FreeBSD 系统上,如果您 stat 存储在 ZFS 数据集上的文件,您通常会注意到该文件的 crtime 字段设置为与 ctime 字段相同的时间。这可能是因为编写文件的应用程序在文件“诞生”并创建其 inode 条目时无法访问设置 crtime 所需的库和内核函数。有一些应用程序/库的示例尝试在应用程序级别保留crtime,例如libarchive(3)(另请参阅:archive_entry_atime(3)),如果在不支持@的文件系统上恢复存档,则会优雅地处理 inode 创建。 987654357@ 字段。但这可能与您的情况无关。

正如您可能想象的那样,有很多应用程序将文件写入文件系统……尤其是在“一切都是文件”的 Unix/POSIX 系统中。我不确定是否需要修改或重新编译旧应用程序以支持这些字段,或者它们是否会从主机系统的 C 库中透明地获取它们。例如,在较旧的 FreeBSD 版本或没有 ext4 的 Linux 系统上使用的应用程序可以在最新的操作系统上以兼容模式运行,但是它们是否能正确处理时间字段是一个很好的问题。

对我来说,以sh birthtime_test 身份运行这个小脚本可以确认我的 FreeBSD 系统上的文件创建时间已“开启”(所有这些系统都使用带有功能标志的 ZFS 帖子 v28ie):

#!/bin/sh
#birthtime_test
uname -r 
if [ -f new_born ] ; then rm -f new_born ; fi

touch new_born 
sleep 3 
touch -a new_born
sleep 3 
echo "Hello from new_born at:" >> new_born 
echo `date` >> new_born
sleep 3 
chmod o+w new_born

stat -f "Name:%t%N
Born:%t%SB
Access:%t%Sa
Modify:%t%Sm 
Change:%t%Sc" new_born

cat new_born

输出:

9.2-RELEASE-p10
Name:   new_born
Born:   May  7 12:38:35 2015
Access: May  7 12:38:38 2015
Modify: May  7 12:38:41 2015 
Change: May  7 12:38:44 2015
Hello from new_born at:
Thu May 7 12:38:41 EDT 2015

(注意:chmod 操作“更改”但不“修改”文件内容 - 这是 echo 命令通过向文件添加内容来执行的操作。请参阅 touch 手册页以了解-m-a 标志)。

这是我现在可以访问的最古老的 FreeBSD 版本。我很想知道 FreeBSD 在发布周期中能处理多长时间(在 ZFS 或 UFS2 文件系统上)。我很确定这已经是很长一段时间的功能了。还有一些 OSX 和 Linux 版本的 ZFS,了解有关此功能的信息会很有用。

还有一件事......

对于简单的“取证”来说,这是一个特别好的功能。假设我们想将我们的new_born 文件发送回时间开始时,回到从未发生过的闰秒以及 - 在一个永恒的时刻 - Unix 诞生的时候...... :-) 1 。我们可以使用touch -d 更改日期,每个人都会认为new_born 是老的和明智的,对吧?

不:

~/ % touch -d "1970-01-01T00:00:01" new_born                
~/ % stat -f "Name:%t%N   
Born:%t%SB
Access:%t%Sa
Modify:%t%Sm
Change:%t%Sc" new_born
Name:   new_born
Born:   May  7 12:38:35 2015
Access: Jan  1 00:00:01 1970
Modify: Jan  1 00:00:01 1970 
Change: May  7 13:29:37 2015

实际上和你看起来一样年轻总是更真实 :-)

时间和Unix——一个既实用又富有诗意的主题:毕竟,什么是“改变”; “修改”或“创造”某物是什么意思?感谢您的精彩帖子 Silvio - 我希望它能够继续存在并收集有用的答案。


如果您可以更具体地说明您对保存、设置和归档文件时间戳字段的要求,您可以改进和概括您的问题。不要误会我的意思:这是一个非常好的问题,并且会在很长一段时间内继续获得投票。

您可以查看 Dylan Leigh 的演示文稿 Forensic Timestamp Analysis of ZFS,甚至联系 Dylan 以获取有关如何访问 crftime 信息的线索。


[1] 一开始有一个传说声称,自很久以前(SSL)以来的秒数从不小于date -u -j -f "%Y-%m-%d:%T" "1970-01-01:00:00:01" "+%s",因为闰秒......

【讨论】:

  • 谢谢。我会尝试联系 Dylan Leigh。虽然在 ZFS 下读取 crtime 很容易(stat 报告它),但挑战在于设置它。
  • 是的。 FreeBSD 的birthtime/crtime 已经有很长一段时间了(我相信在UFS2 上也是如此)所以stat 会显示这一点。您通常会注意到crtimectime 相同,因为创建文件的应用程序并不总是能够访问在inode 的“诞生时间”设置crtime 所需的库和内核函数。
  • 感谢 G. Cito 的扩展回答。我还没有解决方案,但我已经获得了赏金。 (对不起,这是一个吝啬的问题——我是这个小组的新手,当时我只有 99 分,因为有人实际上对这个问题投了反对票!)
  • 哇,谢谢 - 我以为赏金已经过期了。干杯。
  • Cito - 您可能会修改答案的第一段,因为 pax -pe 不会保留出生时间或更改时间。 (man pax 说:“保留所有内容”、用户 ID、组 ID、文件模式位、文件访问时间和文件修改时间。)不过,感谢您向我介绍 pax。 (我还可能会指出一个小错字:它是 cf. 而不是 cf——它来自一个单词,拉丁语“confer”,意思是“比较”。)
猜你喜欢
  • 2022-11-28
  • 2013-11-25
  • 2012-03-01
  • 2014-10-22
  • 2012-01-15
  • 2012-10-11
  • 1970-01-01
  • 1970-01-01
  • 2015-10-29
相关资源
最近更新 更多