贡献者: addis
ZFS 是一个现代化的文件系统,一些特色功能如下。
Windows 对 ZFS 的支持还很低,可能可以在 WSL2 中实现,但更好的方法还是直接用 Linux 挂载 ZFS 然后通过网络硬盘分享。
本文在 Ubuntu 22.04 中测试。ZFS 版本为 zfs-2.1.2-1ubuntu3
,zfs-kmod-2.1.4-0ubuntu0.1
。
sudo apt install zfsutils-linux
dd if=/dev/zero of=虚拟硬盘文件 bs=1M count=500
sudo losetup -fP --show 虚拟硬盘文件
。会返回设备路径如 /dev/loop0
sudo zpool create pool名 /dev/loop0
sudo zpool status
;sudo zpool list
(-v
显示详情)
sudo zfs create pool名/fs名
(fs
是文件系统 file system 的缩写)。创建以后会自动挂载到 /pool名/fs名/
echo "This is a test file." > /pool名/fs名/文件
sudo zfs snapshot pool名/fs名@快照1
echo "This is some additional data." >> /pool名/fs名/文件
sudo zfs diff pool名/fs名@快照1 pool名/fs名
。输出如 M /pool名/fs名/文件
。其中 M
表示 modified。
sudo zfs rollback pool名/fs名@快照1
。现在可以检查 文件
恢复到了之前的版本。
dd if=/dev/zero of=虚拟硬盘文件2 bs=1M count=500
sudo losetup -fP --show 虚拟硬盘文件2
,输出例如 loop1
sudo zpool add pool名 /dev/loop1
sudo zpool destroy pool名
,sudo losetup -d /dev/loop0
sudo zpool status pool名
可以查看各种状态以及 RAID 设置,以及读写错误。
sudo zpool list
(-v
显示详情)
zfs list
可以显示 pool 以及文件系统/dataset。结果如:
NAME USED AVAIL REFER MOUNTPOINT
MyPool 7.25T 13.8T 140K /MyPool
MyPool/fs1 256K 13.8T 256K /MyPool/fs1
MyPool/fs2 7.24T 13.8T 7.24T /MyPool/fs2
zpool iostat -v 2
可以不断刷新实时数据如读写速率。
sudo zpool import
可以查看所有可以用于挂载的 pool。有时候这会需要很久,需要耐心等待!
zpool import pool名
就会挂载这个 pool。
sudo zfs set mountpoint=/挂载/目录 pool名/fs名
。
zfs get mounted,mountpoint pool名/mydataset名
查看是否已经挂载以及挂载目录
sudo zpool export pool名
可以安全弹出 pool,然后可以拔出硬盘或断电。
sudo zfs get all pool名/fs名
可以列出所有当前选项。把 all
换成 选项名
可以列出制定选项。
sudo zfs set 选项=on pool名/fs名
设置某个选项的值。
set
改成 inherit
就相当于关闭这些选项
zfs rename pool名/old_datasetname pool名/dataset名
,需要先 zfs umount pool名/dataset名
。
zfs destroy -r pool名/dataset名
zfs
的程序是非常底层的,系统甚至不知道这些硬盘已经被挂载了。Ubuntu 的 Disk
软件会显示未挂载。System Monitor 也不会显示磁盘的读写速度。
vdev
是 virtual device,一个 pool 中的数据在所有 vdev 上面 strip。也就是说写入一个文件,这个文件的数据会分布在所有 vdev 上。这样可以提高读写速度。
vdev
可以有不同的 RAID(zfs 自带 RAID,不使用标准 RAID),RAID-z1 代表一个冗余相当于普通的 RAID5 至少需要三个 vdev,z2
代表两个冗余至少需要 4 个 vdev,等),也可以是单个盘。但是一个 pool 中只要有一个 vdev 数据丢失,那么就会导致数据彻底无法恢复。
vdev
可以有不同的大小,可以不断往 pool 中加入。zfs 会根据每个 vdev 剩余的容量按比例 strip。
vdev
一旦加入 pool 就不能删除。但可以更换(下文 zpool replace
)。
sudo zpool scrub pool名
可以马上检查整个 pool 的 checksum 是否一致。几秒钟后会在后台开始 scrub,用 sudo zpool status
查看进度和错误数据。期间就算弹出硬盘或者关机,下次挂载还是会继续。
sudo zpool scrub -p pool名
可以暂停 scrub。再次 sudo zpool scrub pool名
可以继续。
scrub
以后如果有任何错误 zpool status
会报告如 scan: scrub repaired 8K in 12:34:17 with 0 errors on Sun Dec 10 12:58:22 2023
这说明用了 12 个小时,修复了 8k 数据,最后给出完成时间。
sudo zfs create -V 8G pool名/swap # 创建一个 8GB 大小的 swap dataset
sudo zfs set primarycache=none pool名/swap # 关闭 RAM 缓存(避免造成死循环!)
sudo zfs set secondarycache=none pool名/swap # 关闭 SSD 缓存
sudo zfs set com.sun:auto-snapshot=false pool名/swap # 关闭自动快照
sudo mkswap -f /dev/zvol/pool名/swap # 初始化 swap
sudo swapon /dev/zvol/pool名/swap # 开启 swap
# 开机加载 swap
sudo echo "/dev/zvol/pool名/swap none swap defaults 0 0" >> /etc/fstab
swapon --show # 列出所有 swap
free -h # 查看 RAM 和 swap 的使用情况
sudo zpool create pool名 raidz1 /dev/sdb /dev/sdc ...
。这会自动挂载到 /pool名
目录。
sudo zfs create pool名/fs名
。
raidz1
组合后 zpool list -v
显示 29.1TB
容量。
sudo zfs unmount pool名
弹出 pool,用 zfs mount
重新挂载。
zpool replace pool名 /dev/sda /dev/sdb
可以把 pool 中的某块磁盘(可以离线)替换成一块新的。新磁盘将没有任何碎片。这种方法理论上可以用来去碎片化(但有可能花很长时间)。
updatedb
和 plocate
搜索 ZFS 中的文件。
sudo zfs set compression=lz4 pool名/fs名
开启 lz4 压缩(cpu 会间断性占用 70% 左右,8 核 16 线程)。可以随时打开或者关闭,只对新数据生效。lz4
是 zfs 最流行的压缩算法。压缩会占用 cpu 但反而有可能会让读写变快! 因为真正需要读写的数据少了。实测在我的 8cpu 电脑上开启最高压缩率算法 gzip-9
并不会让写入变慢。其实如果大文件主要是视频啥的,压缩率其实非常小(我的当前平均压缩率只有 1.04x)。
compressratio
属性可以显示当前的平均压缩率,这只用于查看不能手动设置。
zfs snapshot -r pool名@快照名
可以对整个 pool 做快照,也可以对某个 dataset 做快照
zfs list -t snapshot
查看所有快照。zfs list pool名/ds名 -t snapshot
查看 pool 或者某个 dataset 的快照,注意如果省略 /ds名
,只会显示 pool 级别的快照不会显示包含的 dataset 的快照!
NAME USED AVAIL REFER MOUNTPOINT
pool名/fs名@快照1 0B - 7.84T -
其中 USED
初始是 0,会随着 copy-on-write 慢慢增加
zfs mount -o ro -t snapshot pool名/fs名@快照名 /快照挂载目录
zfs destroy pool名/dataset名@快照名
zfs clone pool名/fs名@快照名 pool名/fs克隆名
。挂载克隆也是一样的语法:zfs mount pool名/fs克隆名 /快照克隆挂载目录
,其实不挂载也可以直接在 /pool名/fs克隆名/
访问。
zfs destroy pool名/fs克隆名
。
zfs create -o encryption=on -o keyformat=passphrase -o keylocation=prompt pool名/newfilesystem
该命令以后命令行会提示你设置新密码并重复确认。
dd if=/dev/urandom of=/path/to/keyfile bs=1 count=32
生成一个随机秘钥
zfs create -o encryption=on -o keyformat=raw -o keylocation=file:///path/to/keyfile pool/dataset
zfs get all pool名/fs名 | grep encrypt
。如果不 grep 则显示所有信息。
import
以后只会自动挂载非加密文件系统,要用 sudo zfs load-key pool名/fs名
命令解密,会提示手动输入密码。然后再用 sudo zfs mount pool名/fs名
才可以挂载加密文件系统。
zfs set keylocation=file:///key/文件 pool名/dataset名
。
cat /proc/spl/kstat/zfs/arcstats | grep c_max
可以查看当前最大允许的 arc 缓存。默认值一般是系统内存的一般。
/etc/modprobe.d/zfs.conf
,加入一行 options zfs zfs_arc_max=字节数
。
zpool add mypool cache /dev/sda
sudo zfs set dedup=on pool名/fs名
开启查重(重复文件可以节约空间,但会使写入速度严重变慢——实测慢一半)。可以随时打开或者关闭,只对新数据生效。
dedup
)都需要 1GB/1TB
的内存。
dedup
,然后再把其中的 1.5TB 拷进另一个文件夹。开始时的 zfs list -v
(省略了一些空白列):
(9:55am)
NAME SIZE ALLOC FREE FRAG CAP DEDUP
pool名 29.1T 4.81T 24.3T 0% 16% 1.00x
raidz1 29.1T 4.81T 24.3T 0% 16.5% -
(7:16am)
NAME SIZE ALLOC FREE FRAG CAP DEDUP
pool名 29.1T 6.64T 22.5T 0% 22% 1.05x
raidz1 29.1T 6.64T 22.5T 0% 22.8% -
ALLOC
的增加跟拷贝文件的大小还差不多。