# 通过systemd设置fedora系统hibernate休眠

> 设置Hibernate休眠模式关键点是设置足够存储笔记本内存内容的swap空间，否则会导致hibernate失败。

我的笔记本安装了双操作系统，有时候希望能够切换到MacOS平台，同时在切换回Linux时候能够保持离开时的工作桌面。

本文是参考Arch Linux文档\[Power management/Suspend and hibernate (简体中文)]\([https://wiki.archlinux.org/index.php/Power\_management/Suspend\_and\_hibernate\_(%E7%AE%80%E4%BD%93%E4%B8%AD%E6%96%87))和\[Enabling](https://wiki.archlinux.org/index.php/Power_management/Suspend_and_hibernate_\(%E7%AE%80%E4%BD%93%E4%B8%AD%E6%96%87\)\)%E5%92%8C\[Enabling) Hibernation in Fedora 23]\([https://baldpenguin.blogspot.com/2016/03/enabling-hibernation-in-fedora-23.html)的一个摘要笔记和实践记录。](https://baldpenguin.blogspot.com/2016/03/enabling-hibernation-in-fedora-23.html\)%E7%9A%84%E4%B8%80%E4%B8%AA%E6%91%98%E8%A6%81%E7%AC%94%E8%AE%B0%E5%92%8C%E5%AE%9E%E8%B7%B5%E8%AE%B0%E5%BD%95%E3%80%82)

实现了Hibernate之后，在双操作系统之间切换非常方便，hibernate之后会切断电源，这样启动时候也是grub界面，但是进入桌面时候就会看出差异：和MacOS一样，每次都回到最初的工作状态，实在是居家旅行编码的一大利器！

## 挂起、睡眠和休眠的区别

暂停并保存当前系统运行状态（前后台进程服务，不包含buff和cache等）有三种方法：

* 挂起到内存：suspend to ram(简称str）

通常被称为挂起，设备通电，低功耗。

挂起也被称为暂停或待机，一般系统一段时间没有操作，系统就会挂起（到内存中），多数外围设备会关闭，某些设备会运行（如键盘鼠标），可以快速响应这些设备从而唤醒系统。

* 挂起到磁盘：suspend to disk(简称std)

通常被称为休眠，设备断电，即设备会关机。

休眠也被称为冬眠（hibernate实为冬眠之意），保存运行状态存到硬盘中，然后关机。下次开机后，系统从硬盘中读取存储的数据并恢复到关机前的状态。

* 混合挂起：suspend to ram and disk(简称strd)

通常被称为睡眠，设备通电，低功耗。

睡眠更准确的名称应该是混合睡眠，所谓混合即存储方式上包含了挂起和休眠两种方式，唤醒时会优先从内存中读取数据，如果设备在此状态下断电（例如笔记本电脑在睡眠时外部电源断掉，而睡眠一段时间后内部电源耗尽），就和休眠一样了。

> `suspend`(挂起到内存)基本无需设置，默认合上笔记本屏幕就是`suspend`。除了电源按钮有些别扭（按一下就关机），但也可参考[修改ACPI事件：更改电源键默认操作](https://github.com/huataihuang/cloud-atlas-draft/tree/6f3204fffc11cf006abd394631e2598d98b415c3/os/linux/kernel/cpu/acpi_events_change_handlepowerkey_action/README.md)进行修改。

## 休眠设置

当前比较新的发行版采用了`systemd`来管理系统，通常可以使用`systemd`休眠管理。此外，也可以选择\[pm-utils]\([https://wiki.archlinux.org/index.php/Pm-utils\_(%E7%AE%80%E4%BD%93%E4%B8%AD%E6%96%87))实现。](https://wiki.archlinux.org/index.php/Pm-utils_\(%E7%AE%80%E4%BD%93%E4%B8%AD%E6%96%87\)\)%E5%AE%9E%E7%8E%B0%E3%80%82)

### 开启休眠

#### 划分合适大小的swap分区

休眠（hibernate）需要将内存中的内容写入磁盘的swap分区，如果swap分区大小比当前休眠所需空间小，则无法保证能够正确地休眠。具体的swap的大小根据个人使用情况（要休眠时的内存占用）而定。

> 在初次安装Fedora操作系统的时候，只划分了内存的一半大小的swap分区。所以我在实践中，首先采用了[缩小lvm卷](https://github.com/huataihuang/cloud-atlas-draft/tree/6f3204fffc11cf006abd394631e2598d98b415c3/os/linux/storage/lvm/decrease_lvm/README.md)将部分分配给`home`逻辑卷的空间划分给`swap`卷，以实现swap空间满足大于内存空间。

#### 添加swap到fstab

> 如果fstab中没有swap磁盘设置则要添加。注意：如果你和我一样对LVM卷做了调整，并且重新执行过`mkswap`，则swap的UUID会修改，使用以下命令获取当前swap的UUID：

```
blkid /dev/mapper/fedora-swap
```

输出类似

```
/dev/mapper/fedora-swap: UUID="f08e5108-ede1-4a51-b479-bf53b1aa5852" TYPE="swap"
```

* 将上述swap的uuid配置添加到`/etc/fstab`：

```
UUID=f08e5108-ede1-4a51-b479-bf53b1aa5852 swap swap defaults 0 0
```

> 不过，实际我的系统在安装Fedora是已经设置过swap，所以默认有一个配置无需修改：

```
/dev/mapper/fedora-swap swap                    swap    defaults        0 0
```

#### 配置 initramfs的resume钩子

**在Arch Linux中配置initramfs**

* 对于`Arch Linux`，采用编辑编辑`/etc/mkinitcpio.conf`，在HOOKS行中添加`resume`钩子

  例如该行原有内容是：

```
HOOKS="base udev autodetect modconf block filesystems keyboard fsck"
```

添加resume后就是：

```
HOOKS="base udev resume autodetect modconf block filesystems keyboard fsck"
```

> 注意: 如果使用`lvm`分区，需要将`resume`放在`lvm`后面，使用lvm的示例：

```
HOOKS="base udev autodetect modconf block lvm2 resume filesystems keyboard fsck"
```

* 重新生成 initramfs 镜像:

```
mkinitcpio -p linux
```

**在Fedora中配置initramfs**

> Fedora使用[Dracut](https://fedoraproject.org/wiki/Dracut)来维护initramfs。详细的信息参考[kernel wiki: dracut](https://dracut.wiki.kernel.org/index.php/Main_Page)。这里简述操作过程，没有涉及Dracut的架构和原理。

* 检查`initramfs`是否包含从hibernation中`resume`

> 注意：Fedora的`dracut`模块已经确保了`resume`位于`lvm`模块之后，类似前述在Arch Linux中设置initramfs所要求的：

执行命令：

```
lsinitrd | less
```

可以看到`dracut`模块包含如下内容

```
dracut modules:
...
lvm
resume
...
```

如果上述`lsinitrd`输出中没有包含上述内容，则针对当前运行的内核执行以下命令：

```
dracut -f -v
```

此时输出将包含`resume`模块

#### 在bootloader中增加resume内核参数

* 编辑 `/etc/default/grub` 在`GRUB_CMDLINE_LINUX_DEFAULT`中添加`resume=/dev/mapper/fedora-swap`

```
GRUB_CMDLINE_LINUX="rd.lvm.lv=fedora/root rd.lvm.lv=fedora/swap rhgb quiet rd.driver.blacklist=nouveau resume=/dev/mapper/fedora-swap"
```

> 如果swap空间在其他分区，例如`sda3`，则可以配置`resume=/dev/sda3`

假如该行的原有内容是：

```
GRUB_CMDLINE_LINUX_DEFAULT=”quiet intel_pstate=enable”
```

添加resume参数后就是：

```
GRUB_CMDLINE_LINUX_DEFAULT="quiet intel_pstate=enable resume=/dev/sda3"
```

* 更新 grub 配置：

如果系统使用EFI

```
grub2-mkconfig -o /boot/efi/EFI/fedora/grub.cfg
```

如果系统使用BIOS（非EFI）

```
grub2-mkconfig -o /boot/grub2/grub.cfg
```

> 不过，在Fedora中，`/boot/grub2/grubenv`是一个软链接到`../efi/EFI/fedora/grubenv`，所以上述两个命令在EFI环境可能是等同的。

检查验证`/boot/grub2/grub.cfg`内容有：

```
        linuxefi /vmlinuz-4.14.8-300.fc27.x86_64 root=/dev/mapper/fedora-root ro rd.lvm.lv=fedora/root rd.lvm.lv=fedora/swap rhgb quiet rd.driver.blacklist=nouveau resume=/dev/mapper/fedora-swap
        initrdefi /initramfs-4.14.8-300.fc27.x86_64.img
```

#### 重启系统

```
systemctl reboot
```

如果重启成功，则尝试hibernate

```
systemctl hibernate
```

或者混合睡眠（结合内存和磁盘，优先从内存加载）

```
systemctl hybrid-sleep
```

## 参考

* \[Power management/Suspend and hibernate (简体中文)]\(<https://wiki.archlinux.org/index.php/Power_management/Suspend_and_hibernate_(%E7%AE%80%E4%BD%93%E4%B8%AD%E6%96%87>))
* [Enabling Hibernation in Fedora 23](https://baldpenguin.blogspot.com/2016/03/enabling-hibernation-in-fedora-23.html) 这篇文章的情况和我相同，非常详细的设置lvm swap卷作为Hibernate


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://huataihuang.gitbook.io/cloud-atlas-draft/os/linux/redhat/system_administration/systemd/hibernate_with_fedora_in_laptop.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
