我正在使用 FreeBSD 10.2,在 root 上使用 ZFS 作为文件系统(zroot01)。我有一个外部硬盘,其 ZFS 文件系统来自另一个 FreeBSD 10.2 系统(zroot02)我想暂时挂载,只读,这样我就可以从中获取一些文件,然后再断开连接。我不我希望外部 ZFS 系统破坏或替换我当前的文件系统,也不希望外部上的数据被损坏/更改。
为了演示我想要实现的目标,如果我使用 UFS,我会执行以下操作:
mount -t ufs -o ro /dev/ada0s2 /mnt/my-fun-mountpoint
.../dev/ada0s2
我的外部驱动器上的分区在哪里,/mnt/my-fun-mountpoint
位于/mnt
我现有操作系统的目录中。
所有的搜索和手册页阅读都没有提供一个清晰的方法来做到这一点。我回答什么做过find 最终接管了我当前的文件系统并将其损坏而无法修复 - 显然不是我正在寻找的结果。我不久前尝试过这样做,所以不幸的是我不记得我尝试过哪些命令。
您能否提供一些关于如何执行此操作的明确指导?预先感谢您的帮助。
答案1
嗯,这确实取决于如何您希望池为只读。不,这不是玩笑。
首先,一些术语:在 ZFS 中,您进口一个游泳池,并且可选山其中的(任何)文件系统。您可以导入池而无需挂载任何文件系统,方法是传递-N
到zpool import
,然后使用 挂载任何所需的文件系统zfs mount
。 (例如,如果您只想访问多个文件系统中的一个,或者您想要执行类似于池脱机清理的操作,那么这是一个完全有效的场景。)
ZFS 并不热衷于真正的只读访问。例如,如果ZFS检测到它能够修复的错误,我相信它会修复错误并将修复的数据写入磁盘即使您以只读方式导入池。我的理解是,在 ZFS 中,“只读”仅适用于用户可见状态池及其数据集。另一方面,如果您将磁盘的二进制副本复制到一个文件(或一组文件),使这些文件真正只读,并尝试从那里导入池,ZFS 将无法导入该池。不管你多么努力,泳池都没有。如果你使文件可写,它就会正常工作。 (实际上我几周前就尝试过这个,尽管使用的是 zvol 和 ZFS拒绝导入池。当我将 zvol 设置为读/写而不是只读时,池导入得很好。)其他文件系统(例如(在 Linux 上)ext4 以及可能其他文件系统)可以稍微优雅地处理这种情况,但 ZFS 犹豫不决。
如果你运气不好,并且没有 ECC RAM安装在您要导入池的系统中,然后 ZFS 尝试更正它遇到的任何错误实际上可能会让事情变得更糟, 虽然意见不同关于这在实践中是否确实存在风险。我个人认为,我足够关心的任何数据都可以通过 ZFS 和快照以及存储级冗余来保护,备份还有诸如此类的应得的ECC RAM 也提供保护,但许多 PC 没有 ECC RAM。
因此,您可以以只读模式导入池,并使用特定的备用根来防止它踩到其他任何东西,但您需要注意这并不一定确实从取证意义上来说是只读的。 (但是,它将确保您不会意外更改池中的任何内容。)要进行只读导入,假设池已命名tank
并且设备节点在 中可用/dev
,您将使用如下命令:
# zpool import tank -d /dev -o readonly=on -R /mnt/someplace
这将查找/dev
包含名称为 的 ZFS 池的任何内容tank
,导入它,临时将池属性设置readonly
为on
(这意味着所有用户启动的写入都将被拒绝)并将其altroot
属性临时设置为/mnt/someplace
。 (这些属性值是“临时的”,因为它们不会作为当前属性值持久保存到磁盘上,因此如果您在没有它们的情况下导出并重新导入池,这些值将恢复正常。它们可能不过,可能会写入池历史记录,一旦池被导入,您可以查看(zpool history tank
如果您愿意的话)。)导入池后,您将在 /mnt/someplace 下看到您的文件,并且具有正常的只读状态访问它们,包括已在池中的数据集上创建的任何快照。
鉴于您的示例,我怀疑您会使用以下内容:
# zpool import zroot02 -d /dev -o readonly=on -R /mnt/my-fun-mountpoint
完成后,请记住干净地导出池:
# zpool export tank
也许
# zpool export zroot02
这将卸载池中的所有文件系统和其他数据集,刷新所有缓冲区(首先需要刷新的范围),将池标记为未进口在所有组成设备上,并执行任何其他必要的内务管理任务,以确保池可以安全地移动到不同的系统并稍后导入。