好像一年多没写东西了诶…… 其实寒假就想写点啥,但都因为拖延症没写成。可见维护博客也是个挺麻烦的事。这次为了避免拖延,写点简单的东西好了。
前言
Archwiki 的 Maximizing performance 一文很早就提到 “Compressing /usr” 这么个优化方式。就是用 squashfs 压缩 /usr(squashfs 是只读的),然后上面加一层 aufs 实现读写支持。好处就是减小磁盘空间占用,从而减轻 I/O 负担,
不过后来 Linux 内核把 aufs 踢出去了,这个优化也就坑了。加上现在 Arch 现在基本把所有东西都放进了 /usr,init 进程对 /usr 依赖特别强,分出去可能会有各种毛病。于是就不再建议搞这个优化了。
前阵子搞学校图书馆的网络启动查询机。实现是:Arch 系统,文件放在 NFS 上的 squashfs 里,用 aufs 读写。于是重新折腾起 aufs + squashfs 了。后来索性在自己机器上也搞了个,不是压 /usr,而是压 /usr/share。这里就记录一下配置吧。
为什么要压缩 /usr/share,而不是别的?
- 除了安装、卸载、升级软件,对 /usr 几乎没有写操作。如果你不进行这些操作,弄个只读的 /usr 都没问题。这就是为什么一般教程只有说压 /usr 的,没有说压 /var 的。
- 压缩 /usr/share 比压整个 /usr 安全,没有 /usr/share 系统也能启动进 single 模式(虽然有些功能会受影响)。
- /usr/share 几乎是 /usr 中占用空间最大的一部分,且其中有很多小文本文件,压缩效率很高。
配置
先说说目录结构。文件系统相关文件都放在 /sfs/usr_share/:
-
squashfs 压缩档:
/sfs/usr_share/filesystem.sfs
-
aufs 只读分支:
/sfs/usr_share/ro
-
aufs 可写分支:
/sfs/usr_share/rw
下面的操作其实都可以开着系统在线完成的,除了最后删除 /usr/share 的部分。
创建 squashfs 压缩档
一条命令的事儿:
mksquashfs /usr/share /sfs/usr_share/filesystem.sfs \
-b 32k -comp lzo -Xcompression-level 9
稍微解释:
- -b 32k:设置 squashfs 块大小为 32k。大概就是一次读取的最小单位。设大点压缩率会更高,但是读取一个 block 所需的 I/O 操作也会变多。所以要取个适当的值。我试了,32k 就差不多,再大压缩率增加的也不明显。(这主要是因为 /usr/share 里大多是很小的碎文件)
- -comp lzo:压缩算法设置为 lzo。这个压缩算法的特点是快速、省资源,压缩比一般般。但这样其实正好适合文件系统压缩,本来文件系统压缩就是牺牲内存/CPU资源来节省I/O资源的。可以看看网上的评测,这个压缩率比 xz/lzma 差一些,但压缩/解压速度快了很多。
- 注意压缩算法千万别选 lz7。这个算法也是跟 lzo 差不多的特点,不过内核的 squashfs 模块似乎还不支持该算法……
- -Xcompression-level 9:使用最大比率的 lzo 压缩。据说这样只是压缩速度会变慢,解压速度几乎不受影响。
写 systemd 的 mount 单元
按道理说,应该在 fstab 里加上相关项就可以了。但实际上我遇到了很严重的问题,开机经常没挂上 /usr/share。我没仔细追原因,感觉好像是因为 systemd 对挂载顺序作出了些调整,导致了一些问题。最后试了试 systemd 引入的新东西,解决了问题。
众所周知,systemd 造了好多轮子,什么 crontab、网络管理器、日志服务 它都想给接替了。fstab 也是这样,systemd 引入了 .mount 单元这么个东西,用于控制文件系统挂载。
虽然 Arch 还没抛弃 fstab,但其实 fstab 中有些内容已经被 systemd 完全取代了。老 Arch 用户可能记得,以前 /dev、/tmp 的挂载都是要写进 fstab 的,但现在都不用写了。Arch 用户可以看看 systemd 包提供的 /usr/lib/systemd/system/tmp.mount
这个文件,就是 /tmp 的挂载配置。内容很好理解,就不贴了。
正如 systemd 引入的各种单元(unit)一样,mount 单元也可以写各种依赖啊什么的东西,从这点来讲它比 fstab 的功能要强大。这里挂载 /usr/share 就要用到依赖关系:可读分支要在 /usr/share 挂载之前完成挂载。
直接贴文件:
[Unit] Description = /usr/share, read-only branch [Mount] What = /sfs/usr_share/filesystem.sfs Where = /sfs/usr_share/ro Type = squashfs Options = defaults [Install] WantedBy = local-fs.target
[Unit] Description = /usr/share Requires = sfs-usr_share-ro.mount After = sfs-usr_share-ro.mount [Mount] What = none Where = /usr/share Type = aufs Options = br:/sfs/usr_share/rw=rw:/sfs/usr_share/ro=ro [Install] WantedBy = local-fs.target
内容也很好看懂。Requires、After 这和 systemd service 的写法基本一致(其实我也不太懂),[Mount] 下就是挂载的说明了,What 后是要挂载的文件系统,Where 是挂载到的地方,Type 是文件系统类型,Options 是挂载参数。相当于:
mount -t <Type> -o <Options> <What> <Where>
不知道有人注意到这个文件名没,尤其是第一个。sfs-usr_share-ro.mount 这样命名其实是 systemd 强制要求的(抄自 man systemd.mount):
反正就是要和你挂载到的路径一致,把路径里的「/」换成「 -」。挺蛋疼的。
测试、清理
其实现在重启应该就可以了,/usr/share 放那儿反正会被 mount 盖掉。重启后确认 /usr/share 确实挂上 aufs 了,原来的文件是否删除就看心情了吧。
后期保养
说句实话,给 Debian stable 之类的上这个优化可能更有效。Arch 你得经常滚啊,滚一滚 aufs 可写分支就变得很大,这时就得重新压一下 squashfs 了。
重新压的步骤和前面差不多,就是把你现在的 /usr/share 当成没压的重新压一遍,把可写分支清空。不过清空可写分支的操作得离线进行(至少要进 single 模式卸载掉原来的 aufs)。注意安全,不多说了。
随便写写,没看懂的人千万不要乱试哦!
2014年7月17日 00:14
自从有了 btrfs,还有人用这种方法压缩么……
2014年7月18日 21:57
这个能提高多少效率有对比过吗?能省多少空间呀?
我曾在 aufs 上跑 Ubuntu 的 lxc,结果经常出来 NFS Stale Handle 错误……
@Iven: btrfs 放 / 容易出问题搞死系统。
2014年8月31日 13:47
这个在 initramfs 里挂载的话就没 systemd 那些麻烦事儿了吧?
2022年8月04日 13:00
Spice Money is a multidisciplinary digital and Banking Services, has been popularly in use by individuals. Spice Money login seen to promote banking services in rural areas with AePS, where the trending Apps don’t make their way. Having used this tool the individual can make their payments for different services such as Gas Bill, Electricity Bill, PAN card, and many others. Spice b2b The banking services happen through Aadhaar Card like settlement, balance inquiry, money withdrawal and more easily processed using Spice Money. Spice Money is a multidisciplinary digital and Banking Services, has been popularly in use by individuals. Spice Money login seen to promote banking services in rural areas with AePS, where the trending Apps don’t make their way.