本文将引导您完成休眠的手动设置 Fedora Linux 36 工作站使用 BTRFS 并且基于 github 上 eloylp 的要点.
目标和理由
休眠将您机器的当前运行时状态——有效地存储在您的 RAM 中的内容到磁盘上并执行干净的关机。 下次启动时,此状态会从磁盘恢复到内存,因此包括打开的程序在内的所有内容都是您离开它的方式。
Fedora 工作站使用 ZRAM。 这是一种在 RAM 的一部分内使用压缩进行交换的复杂方法,以避免较慢的磁盘交换文件。 不幸的是,这意味着在关闭机器电源时,您没有永久空间来在休眠时移动 RAM。
这个怎么运作
该技术将 systemd 和 dracut 配置为在磁盘上的临时交换文件中存储和恢复 RAM 的内容。 交换文件在休眠之前创建并在休眠后立即删除,以避免 ZRAM 出现问题。 不建议将持久交换文件与 ZRAM 结合使用,因为它会产生一些影响系统稳定性的令人困惑的问题。
关于兼容性和期望的一句话
遵循本指南的休眠可能无法在您的特定机器上完美运行。 由于某些驱动程序可能存在的缺点,您可能会在从休眠状态恢复后遇到故障,例如无法工作的 wifi 或显示。 在这种情况下,请随时联系 github上的要点,或尝试本文底部故障排除部分的提示。
本文中介绍的更改与 systemd hibernation.service 和 hibernation.target 单元相关联,因此如果您不启动休眠,它们不会自行执行,也不会干扰您的系统。 话虽如此,如果它不起作用,它仍然会增加一些您可能想要删除的小膨胀。
冬眠 Fedora 工作站
第一步是创建一个 btrfs 子卷来包含交换文件。
$ btrfs subvolume create /swap
为了计算交换文件的大小,请使用 swapon 来获取 zram 设备的大小。
$ swapon NAME TYPE SIZE USED PRIO /dev/zram0 partition 8G 0B 100
在这 example 该机器有 16G 的 RAM 和一个 8G 的 zram 设备。 ZRAM 存储的系统 RAM 量大约是您的一部分 RAM 中压缩的系统 RAM 量的两倍。 让它沉入一会儿。 这意味着这台机器的内存总共可以容纳 8G * 2 + 8G 的 RAM,这等于 24G 的未压缩数据。 使用以下命令创建和配置交换文件。
$ touch /swap/swapfile # Disable Copy On Write on the file $ chattr +C /swap/swapfile $ fallocate --length 24G /swap/swapfile $ chmod 600 /swap/swapfile $ mkswap /swap/swapfile
修改 dracut 配置并重建您的 initramfs 以包含
resume 模块,因此它可以稍后在启动时恢复状态。
$ cat <<-EOF | sudo tee /etc/dracut.conf.d/resume.conf add_dracutmodules+=" resume " EOF $ dracut -f
为了配置 grub 以告诉内核使用交换文件从休眠中恢复,您需要 UUID 和物理偏移量。
使用以下命令确定交换文件的 UUID 并记下它。
$ findmnt -no UUID -T /swap/swapfile dbb0f71f-8fe9-491e-bce7-4e0e3125ecb8
计算正确的偏移量。 为了做到这一点,不幸的是,您需要 gcc 和 btrfs_map_physical 工具的来源,它计算磁盘上交换文件的物理偏移量。 在您放置源代码的目录中调用 gcc 并运行该工具。
$ gcc -O2 -o btrfs_map_physical btrfs_map_physical.c $ ./btrfs_map_physical /path/to/swapfile FILE OFFSET EXTENT TYPE LOGICAL SIZE LOGICAL OFFSET PHYSICAL SIZE DEVID PHYSICAL OFFSET 0 regular 4096 2927632384 268435456 1 <4009762816> 4096 prealloc 268431360 2927636480 268431360 1 4009766912 268435456 prealloc 268435456 3251634176 268435456 1 4333764608 536870912 prealloc 268435456 3520069632 268435456 1 4602200064 805306368 prealloc 268435456 3788505088 268435456 1 4870635520 1073741824 prealloc 268435456 4056940544 268435456 1 5139070976 1342177280 prealloc 268435456 4325376000 268435456 1 5407506432 1610612736 prealloc 268435456 4593811456 268435456 1 5675941888
PHYSICAL OFFSET 列中的第一个值是相关值。 在上述 example 这是 4009762816.
记下您从 getconf PAGESIZE 获得的页面大小。
通过物理偏移除以页面大小来计算内核 resume_offset。 在这 example 即 4009762816 / 4096 = 978946。
更新您的 grub 配置文件并添加 resume 和 resume_offset 内核命令行参数。
grubby --args="resume=UUID=dbb0f71f-8fe9-491e-bce7-4e0e3125ecb8 resume_offset=2459934" --update-kernel=ALL
创建的交换文件仅用于系统关闭和启动的休眠阶段,因此未在 fstab 中配置。 Systemd 单元控制此行为,因此创建两个单元 hibernate-preparation.service 和 hibernate-resume.service。
$ cat <<-EOF | sudo tee /etc/systemd/system/hibernate-preparation.service [Unit] Description=Enable swap file and disable zram before hibernate Before=systemd-hibernate.service [Service] User=root Type=oneshot ExecStart=/bin/bash -c "/usr/sbin/swapon /swap/swapfile && /usr/sbin/swapoff /dev/zram0" [Install] WantedBy=systemd-hibernate.service EOF $ systemctl enable hibernate-preparation.service $ cat <<-EOF | sudo tee /etc/systemd/system/hibernate-resume.service [Unit] Description=Disable swap after resuming from hibernation After=hibernate.target [Service] User=root Type=oneshot ExecStart=/usr/sbin/swapoff /swap/swapfile [Install] WantedBy=hibernate.target EOF $ systemctl enable hibernate-resume.service
Systemd 对登录和休眠进行内存检查。 为了避免在交换文件和 zram 之间来回移动内存时出现问题,请禁用其中一些。
$ mkdir -p /etc/systemd/system/systemd-logind.service.d/ $ cat <<-EOF | sudo tee /etc/systemd/system/systemd-logind.service.d/override.conf [Service] Environment=SYSTEMD_BYPASS_HIBERNATION_MEMORY_CHECK=1 EOF $ mkdir -p /etc/systemd/system/systemd-hibernate.service.d/ $ cat <<-EOF | sudo tee /etc/systemd/system/systemd-hibernate.service.d/override.conf [Service] Environment=SYSTEMD_BYPASS_HIBERNATION_MEMORY_CHECK=1 EOF
重新启动计算机以使更改生效. 如果您不先重新启动,则以下 SELinux 配置将不起作用。
SELinux 还不喜欢休眠尝试。 用新政策改变它。 一种简单但“粗暴”的方法是启动休眠并通过 audit2allow 使用此失败尝试的审核日志。 以下命令将失败,返回登录提示。
systemctl hibernate
再次登录后检查审核日志,编译策略并安装它。 -b 选项过滤来自上次引导的审计日志条目。 -M 选项将所有过滤规则编译成一个模块,然后使用 semodule -i 安装该模块。
$ audit2allow -b #============= systemd_sleep_t ============== allow systemd_sleep_t unlabeled_t:dir search; $ cd /tmp $ audit2allow -b -M systemd_sleep $ semodule -i systemd_sleep.pp
再次通过 systemctl hibernate 检查休眠是否正常工作。 恢复后检查 ZRAM 确实是唯一的活动交换设备。
$ swapon NAME TYPE SIZE USED PRIO /dev/zram0 partition 8G 0B 100
您现在已配置休眠。
GNOME Shell 休眠集成
您可能希望在 GNOME Shell “关机/注销”部分添加一个休眠按钮。 查看扩展程序 休眠状态按钮 这样做。
故障排除
解决任何问题的第一个地方是通过 journalctl -b。 在尝试休眠后,查看日志的末尾,以查明告诉您可能出现什么问题的日志条目。
错误信息的另一个来源是问题报告工具。 尤其是不常见但更具体到您的硬件配置的问题。 在尝试休眠之前和之后查看它,看看是否出现了问题。 通过 BugZilla 跟进任何问题,看看其他人是否遇到类似问题。
还原更改
要撤消上述更改,请遵循以下清单:
- 删除交换文件
- 删除交换子卷
- 删除 dracut 配置并重建 dracut
- 通过 grubby –remove-args= 删除内核命令行参数
- 禁用和删除休眠准备和恢复服务
- 删除 systemd-logind.service 和 systemd-hibernation.service 的 systemd 覆盖
- 通过 semodule -r systemd_sleep 删除 SELinux 模块
学分和其他资源
本文是主要基于 eloylp 工作的社区努力。 作为本文的作者,我想澄清一下,我参与了讨论以推进这背后的要点,但更多的人为这项工作做出了贡献。 确保检查 github上的讨论.
已经有一些 ansible 剧本和 shell 脚本来自动化本指南中描述的过程。 为了 example 通过以下方式查看 shell 脚本 克罗温 和 皮特里扎克 或 ansible 剧本 约普
见 拱维基 有关怎样计算交换文件偏移量的完整指南。