电源管理/挂起与休眠

来自 Arch Linux 中文维基

多种方法可用于挂起,特别是:

Suspend to idle(挂起到空闲状态)
英特尔称之为 S0ix,微软称之为现代待机(以前是“保持网络连接的待机”),内核称之为 S2Idle。设计用于替代 S3 睡眠状态的支持系统,提供相同的节能,但大大减少了唤醒时间。
提示:虽然这种状态会导致 WindowsmacOS 上的电池消耗问题,因为它们支持在这种状态下唤醒设备进行网络活动,但 Linux 软件生态系统目前没有使用这种特性,应该不会受到影响。
Suspend to RAM(挂起到内存,通称挂起)
ACPI 定义的 S3 睡眠状态。通过将机器中大多数和 RAM 不相关的部件断电来工作,RAM 是恢复机器状态所必需的。由于可以节省大量电力,建议笔记本电脑在使用电池运行且盖子关闭时(或用户在一段时间内处于非活动状态)自动进入此模式。
Suspend to disk(挂起到硬盘,通称休眠)
ACPI 定义的 S4 睡眠状态。将机器状态保存到交换空间并关闭机器。再次开机后,恢复状态。直到开机前,机器都不会有任何待机功耗
Hybrid suspend(混合挂起)
挂起和休眠的混合,有时称为挂起到两者。将机器状态保存到交换空间,但并不关闭电脑,而是调用默认的挂起机制,从而使未掉电的电脑能立刻恢复。如果电脑掉电(断电且电池耗尽),系统也可以从硬盘的交换空间中恢复,尽管比从内存中恢复慢一些。

以上三者均由内核提供基础功能,再由高级接口进行了一定调整,以适配一些较为复杂的硬件与内核模块(如显卡唤醒后的重新初始化)

内核接口 (swsusp)[编辑 | 编辑源代码]

注意: 尽管可以直接使用内核接口,这更快,因为不需要额外的用户空间处理,但建议使用高级接口。它通过执行额外的安全检查以及提供预挂起和后挂起钩子机制来更好地设置硬件时钟、恢复无线等,从而做得更好。

可以通过直接告知内核中的软件挂起代码(swsusp)进入挂起状态,具体的方法和状态取决于硬件支持的程度。在现代内核中,向 /sys/power/state 写入特定字符串是触发此挂起的主要机制。

更多信息详见内核文档

高级接口 (systemd)[编辑 | 编辑源代码]

这篇文章的某些内容需要扩充。

原因: systemd v256 支持使用新的 systemctl sleep 命令自动选择最合适的睡眠操作。 [1] (在 Talk:电源管理/挂起与休眠 中讨论)
注意: 高级接口旨在提供可执行的二进制文件/脚本,用于执行挂起/休眠操作,并提供将额外的准备/清理工作挂钩到所述进程的方法。有关电源按钮、菜单点击或笔记本盖事件自动进入睡眠状态,请参阅 Power management#ACPI events

systemd 提供了用于挂起、休眠和混合挂起的原生命令。这是 Arch Linux 中使用的默认接口。

systemctl suspend 开箱即用。要使 systemctl hibernate 在您的系统上运行,您可能需要遵循 #休眠 中的说明。

还有两种结合挂起和休眠的模式:

  • systemctl hybrid-sleep 将系统同时挂起到 RAM 和磁盘,因此完全断电不会导致数据丢失。 此模式也称为“同时挂起”。
  • systemctl suspend-then-hibernate 最初会尽可能将系统挂起到 RAM 中,然后使用 RTC 警报将其唤醒并休眠。RTC 警报由 systemd-sleep.conf(5) 中的 HibernateDelaySec 设置。默认值通过估计电池放电率来设置,以使系统保持 5% 的电池电量,或者在没有电池的情况下保持两小时。 估计值是根据 systemd-sleep.conf(5)SuspendEstimationSec 指定的时间后电池电量变化获得的,该系统将短暂唤醒进行测量(如果系统从挂起中手动唤醒,也会进行测量)。

关于配置睡眠或休眠钩子,详见电源管理#睡眠钩子。又见 systemctl(1)systemd-sleep(8)systemd.special(7)

更改挂起方法[编辑 | 编辑源代码]

在 S0ix 挂起不能提供与常规 S3 睡眠相同的节能的系统上,或者当节能优于快速的恢复时间时,可以更改默认挂起方法。

提示:S0ix 被认为可以提供与 S3 睡眠相同或更好的节能,请参阅以下英特尔博客文章 如何在 Linux 中实现 S0ix 状态Linux S0ix 故障排除在 Linux 上高效空闲:一个案例研究,以检查您是否可以使其按预期工作。英特尔用户可以使用 S0ixSelftestTool.


运行以下命令以查看硬件公开支持的所有挂起方法(当前方法包裹在方括号中显示[2]):

$ cat /sys/power/mem_sleep
[s2idle] shallow deep
mem_sleep 中支持的睡眠状态
mem_sleep 字符串 睡眠状态
s2idle suspend-to-idle
shallow standby
deep suspend-to-RAM

如果您的硬件没有公布 deep 睡眠状态,请首先检查 UEFI 是否公布了它的某些设置,通常是在“电源(Power)”或“睡眠状态(Sleep state)”或类似的用词下,并使用名为 Windows 10, Windows and LinuxS3/Modern standby support 关于 S0ix 的选项,以及 Legacy, Linux, Linux S3S3 enabled 关于 S3 睡眠的选项。否则,您可以继续使用 s2idle,考虑使用休眠或尝试给 DSDT 表打补丁(或在线查找补丁版本)。

注意: 最后一个解决方案很可能会引起问题。自从 Windows 系统默认使用 “现代待机 ”后,制造商已经停止修复 ACPI S3 状态的错误:如果它们主动地不公布它,它可能会在某种程度上出问题。

通过在更改睡眠方法后测试几个睡眠周期,验证你的硬件没有 S3 睡眠问题:

# echo deep > /sys/power/mem_sleep

如果没有发现任何问题,可以通过 systemd-sleep.conf(5) 中的 MemorySleepMode 选项使更改永久化。

/etc/systemd/sleep.conf.d/mem-deep.conf
[Sleep]
MemorySleepMode=deep

或者通过mem_sleep_default=deep 内核参数

在一些相反的情况下,有缺陷的固件公布支持 deep 睡眠,但只支持 s2idle。在这种情况下,通过选项中的 SuspendState 可以以另一种方法使用 s2idle

/etc/systemd/sleep.conf.d/freeze.conf
[Sleep]
SuspendState=freeze

休眠[编辑 | 编辑源代码]

这篇文章的某些内容需要扩充。

原因: Add instructions for changing the hibernation image compression (HIBERNATION_COMP_LZ4 or HIBERNATION_COMP_LZO at build time, hibernate.compressor= at boot time and /sys/module/hibernate/parameters/compressor at runtime).[3] (在 Talk:电源管理/挂起与休眠 中讨论)

为了使用休眠功能,您必须创建一个 swap 分区或文件、#配置 initramfs 以便在早期用户空间启动恢复过程,并指定交换空间的位置以便 initramfs 可以访问,例如:由 systemd 定义的 HibernateLocation EFI 变量或 resume= 内核参数。下面详细描述了这三个步骤。

注意:


swap分区/文件的大小[编辑 | 编辑源代码]

即使swap比内存小,成功休眠的可能性仍然不小。参见内核文档中的“image_size”部分以获取关于 image_size sysfs(5) pseudo-file 的更多信息。

您可以减小 /sys/power/image_size 的设定值以使休眠镜像尽可能小(对于小交换分区),或者增大它以加快休眠过程(也许)。对于 RAM 很大的系统,较小的值可能会显著提高系统从休眠中恢复的速度。这是一个临时文件,参阅Systemd#临时文件以固定你的修改。

/etc/tmpfiles.d/hibernation_image_size.conf
	
#    Path                   Mode UID  GID  Age Argument
	
w    /sys/power/image_size  -    -    -    -   0
	

休眠镜像不能跨多个交换分区和/或交换文件。它必须完全适配一个交换分区或一个交换文件[4]

配置 initramfs[编辑 | 编辑源代码]

  • 当使用一个 busybox-based 的 initramfs 时(这是默认值),/etc/mkinitcpio.conf 中需要 resume 钩子。无论是通过卷标还是通过 UUID,交换分区都是通过 udev 设备节点来引用的,因此 resume 钩子必须在 udev 钩子之后。这是一个使用默认钩子配置的示例:
HOOKS=(base udev autodetect keyboard microcode modconf kms keyboard keymap consolefont block filesystems resume fsck)
编辑后记得重新生成 initramfs
注意: 如果使用堆叠存储作为交换空间,例如 dm-cryptRAIDLVM,则最终映射的设备必须在早期用户空间中可用,并且在恢复过程启动之前。也就是说,在这样的设置中,resume 钩子必须放在诸如 encryptlvm2 等钩子之后。
  • 当使用带有 systemd 钩子的 initramfs 时,已经提供了恢复机制,不需要额外添加钩子。

传递休眠位置到 initramfs[编辑 | 编辑源代码]

当系统休眠时,内存映像被转储到交换空间,其中也包括挂载文件系统的状态。因此,休眠位置必须提供给 initramfs,即在挂载根文件系统之前,以便从休眠状态恢复。

systemd v255 和 mkinitcpio v38 开始,当系统运行在 UEFI 上时,systemd-sleep(8) 将自动选择合适的交换空间进行休眠,并且所用交换空间的信息存储在 HibernateLocation EFI 变量中。在下次启动时,systemd-hibernate-resume(8) 从 EFI 变量读取位置,系统恢复。这意味着除非系统使用遗留 BIOS 或您想选择与自动选择的不同的交换空间,否则以下步骤不是必需的。

手动指定休眠位置[编辑 | 编辑源代码]

可以传递内核参数 resume=swap_device。其中 swap_device 遵循 persistent block device naming。例如:

  • resume=UUID=4209c845-f495-4c43-8a03-5363dd433153
  • resume="PARTLABEL=swap分区卷标"
  • resume=/dev/archVolumeGroup/archLogicalVolume——如果swap在LVM逻辑卷上(UUID 和 标签应该同样可以工作)

内核参数只有在重新启动后才会生效。要想不重启而马上休眠,请从lsblk获取卷的主要和次要设备号,并 echo major:minor/sys/power/resume

例如,如果交换设备是8:3

# echo 8:3 > /sys/power/resume

如果使用交换文件,请继续查看#获取交换文件偏移量

获取交换文件偏移量[编辑 | 编辑源代码]

使用交换文件进行休眠时,文件系统所在的块设备应该在 resume= 中指定,并且还需要通过 resume_offset= 内核参数 指定交换文件的物理偏移量。 [5]

在除 Btrfs 之外的文件系统上,可以通过运行 filefrag -v 交换文件 来获取 resume_offset= 的值。输出为表格格式,所需的值位于第一行 physical_offset 列中。

例如:

# filefrag -v /swapfile
Filesystem type is: ef53
File size of /swapfile is 4294967296 (1048576 blocks of 4096 bytes)
 ext:     logical_offset:        physical_offset: length:   expected: flags:
   0:        0..       0:      38912..     38912:      1: 
   1:        1..   22527:      38913..     61439:  22527:             unwritten
   2:    22528..   53247:     899072..    929791:  30720:      61440: unwritten
...

在本例中,resume_offset= 的值是首先出现的那个 38912

Alternatively, to directly acquire the offset value:

# filefrag -v swap_file | awk '$1=="0:" {print substr($4, 1, length($4)-2)}'

For Btrfs, do not try to use the filefrag tool, since the "physical" offset you get from filefrag is not the real physical offset on disk; there is a virtual disk address space in order to support multiple devices.[6] Instead, use the btrfs-inspect-internal(8) command. E.g.:

# btrfs inspect-internal map-swapfile -r swap_file
198122980

In this example, the kernel parameter would be resume_offset=198122980.

To apply the change immediately (without rebooting), echo the resume offset to /sys/power/resume_offset. For example, if the offset is 38912:

# echo 38912 > /sys/power/resume_offset
提示:The following command may be used to identify the backing device of the swap file: findmnt -no UUID -T swap_file
注意: For a stacked block device such as an encrypted container (LUKS), RAID or LVM, the resume parameter must point to the unlocked/mapped device that contains the file system with the swap file.

不要尝试使用 filefrag 工具,在 Btrfs 上,从 filefrag 获得的 physical_offset 不是实际 offset。因为 btrfs 有一个虚拟磁盘地址空间以支持多个设备。[7]

btrfs-progs 6.1,提供了一个命令来检查用于休眠的交换文件及其偏移值。参见 btrfs-inspect-internal(8)

# btrfs inspect-internal map-swapfile -r path/to/swapfile
198122980

Maintaining swap file for hibernation with zram[编辑 | 编辑源代码]

提示:Instead of the following setup which involves multiple swap spaces, zswap can be used to establish a similar behavior.

It is possible to solve the hibernation problem with zram RAM-only swap by maintaining two or more swap spaces at the same time. systemd will always ignore zram block devices before triggering hibernation [8], therefore keeping both spaces enabled should work without further intervention.

After configured the swap file, follow the zram page. Make sure zram has the higher swap priority (e.g. pri=100).

注意:

休眠到精简配置的LVM卷中[编辑 | 编辑源代码]

在精简配置的LVM卷中休眠是可能的,但必须确保该卷已完全分配。否则系统将无法从中恢复,参见 FS#50703

可以通过简单地用零填充来完全分配LVM卷。例如:

# dd if=/dev/zero of=/dev/vg0/swap bs=1M status=progress

想确认卷是否已完全被分配,使用:

# lvs
 LV                   VG  Attr       LSize   Pool Origin    Data%  Meta%  Move Log Cpy%Sync Convert
 swap                 vg0 Vwi-aot--- 10.00g  pool           100

完全分配的卷将显示为具有100%的Data%

警告: 不要在用于休眠的精简配置的swap分区上使用TRIM,即:不要在/etc/fstab使用discard,也不要在swapon时加入-d--discard参数。否则已被使用的空间会被重新去分配

Disable zswap writeback to use the swap space only for hibernation[编辑 | 编辑源代码]

In Linux 6.8, zswap gained a per-cgroup option to disable writeback. By using systemd unit setting MemoryZSwapWriteback (see systemd.resource-control(5) § Memory Accounting and Control) in all possible unit types, zswap writeback can be effectively disabled entirely. This allows to use zswap just like zram with the added benefit of supporting hibernation.

To avoid having to manually create twelve top level per-type drop-in files (for system and user scope, service, slice, socket, mount, swap units types), install zswap-disable-writebackAUR. Reboot for the settings to take effect.

Try to perform memory intensive tasks and confirm that zswap has not written anything to disk:

# cat /sys/kernel/debug/zswap/written_back_pages
0

Sleep hooks[编辑 | 编辑源代码]

Custom systemd units[编辑 | 编辑源代码]

systemd starts suspend.target, hibernate.target, hybrid-sleep.target, or suspend-then-hibernate.target for each sleep state, respectively. All the aforementioned targets pull in sleep.target. Any of the targets can be used to invoke custom units before or after suspend/hibernate. Separate files should be created for user actions and root/system actions. Examples:

/etc/systemd/system/user-suspend@.service
[Unit]
Description=User suspend actions
Before=sleep.target

[Service]
User=%I
Type=forking
Environment=DISPLAY=:0
ExecStartPre= -/usr/bin/pkill -u %u unison ; /usr/local/bin/music.sh stop
ExecStart=/usr/bin/sflock
ExecStartPost=/usr/bin/sleep 1

[Install]
WantedBy=sleep.target
/etc/systemd/system/user-resume@.service
[Unit]
Description=User resume actions
After=suspend.target

[Service]
User=%I
Type=simple
ExecStart=/usr/local/bin/ssh-connect.sh

[Install]
WantedBy=suspend.target

Enable user-suspend@user.service and/or user-resume@user.service for the change to take effect.

注意: As screen lockers may return before the screen is "locked", the screen may flash on resuming from suspend. Adding a small delay via ExecStartPost=/usr/bin/sleep 1 helps prevent this.

For root/system actions:

/etc/systemd/system/root-suspend.service
[Unit]
Description=Local system suspend actions
Before=sleep.target

[Service]
Type=simple
ExecStart=-/usr/bin/pkill sshfs

[Install]
WantedBy=sleep.target
/etc/systemd/system/root-resume.service
[Unit]
Description=Local system resume actions
After=suspend.target

[Service]
Type=simple
ExecStart=/usr/bin/systemctl restart mnt-media.automount

[Install]
WantedBy=suspend.target

Combined sleep/resume unit[编辑 | 编辑源代码]

With the combined unit file, a single hook does all the work for different phases (sleep/resume) and for different targets.

Example and explanation:

/etc/systemd/system/wicd-sleep.service
[Unit]
Description=Wicd sleep hook
Before=sleep.target
StopWhenUnneeded=yes

[Service]
Type=oneshot
RemainAfterExit=yes
ExecStart=-/usr/share/wicd/daemon/suspend.py
ExecStop=-/usr/share/wicd/daemon/autoconnect.py

[Install]
WantedBy=sleep.target
  • RemainAfterExit=yes: After started, the service is considered active until it is explicitly stopped.
  • StopWhenUnneeded=yes: When active, the service will be stopped if no other active service requires it. In this specific example, it will be stopped after sleep.target is stopped.
  • Because sleep.target has StopWhenUnneeded=yes, the hook is guaranteed to start/stop properly for different tasks.

Hooks in /usr/lib/systemd/system-sleep[编辑 | 编辑源代码]

注意: This method is considered a hack by systemd according to systemd-sleep(8). systemd-sleep will run these hooks concurrently rather than one after another. For a more well-defined interface with support for ordering, see #Custom systemd units.

systemd-sleep runs all executables in /usr/lib/systemd/system-sleep/, passing two arguments to each of them:

  1. Either pre or post, depending on whether the machine is going to sleep or waking up.
  2. suspend, hibernate or hybrid-sleep, depending on which is being invoked.

The output of any custom script will be logged by systemd-suspend.service, systemd-hibernate.service or systemd-hybrid-sleep.service. You can see its output in systemd's journalctl:

# journalctl -b -u systemd-suspend.service

An example of a custom sleep script:

/usr/lib/systemd/system-sleep/example.sh
#!/bin/sh
case $1/$2 in
  pre/*)
    echo "Going to $2..."
    ;;
  post/*)
    echo "Waking up from $2..."
    ;;
esac

Do not forget to make your script executable.


Tips and tricks[编辑 | 编辑源代码]

Disable sleep completely[编辑 | 编辑源代码]

When using a device as e.g a server, suspending/hibernating might not be needed or it could even be undesired. Each sleep state can be disabled through systemd-sleep.conf(5):

/etc/systemd/sleep.conf.d/disable-sleep.conf
[Sleep]
AllowSuspend=no
AllowHibernation=no
AllowHybridSleep=no
AllowSuspendThenHibernate=no

英特尔快速启动技术(Intel Rapid Start Technology,IRST)[编辑 | 编辑源代码]

英特尔快速启动技术是一种休眠的固件解决方案,允许在预定义的时间间隔或电池状态后从休眠。这应该比常规休眠更快更可靠,因为它是由固件而不是在操作系统级别完成的。通常,它必须在固件中启用,固件还支持设置暂停/电池事件触发休眠后的持续时间,然而,尽管固件中支持 IRST,但某些设备仅允许通过英特尔的 Windows 驱动程序进行配置。在这种情况下,下面描述的 intel-rst 内核模块应该能够在 Linux 下配置事件。

启用英特尔快速启动技术(IRST)后,从深度睡眠中恢复需要“比从 S3 恢复长几秒,但比从休眠中恢复快得多”。

许多基于英特尔的系统都支持 IRST 固件,但需要在 SSD(而不是 HDD)上使用特殊分区。Windows 的 OEM 部署可能已经有一个预先存在的 IRST 分区,可以在 Arch Linux 安装过程中保留(而不是擦除和重新分区整个 SSD)。它应该显示为与系统 RAM 大小相等的未格式化分区。

警告: 英特尔快速启动分区未加密;“如果您使用基于软件的磁盘加密,英特尔建议禁用英特尔快速启动技术”。[9]

但是,如果您打算擦除并重新分区整个驱动器(或者已经这样做了),那么如果您也计划使用该技术,则必须重新创建IRST分区。这可以通过创建一个与系统 RAM 大小相等的空分区,并将其分区类型设置为 GUID D3BFE2DE-3DAF-11DF-BA40-E3A556D89593(对于 GPT 分区)或 ID 0x84(对于 MBR 分区)来实现。您可能还需要在系统的固件设置中启用对IRST的支持。

提示:可以在系统的固件设置中调整 IRST 启动前(挂起后)的持续时间。

IRST 休眠过程的持续时间(即将RAM的全部内容复制到特殊分区)取决于系统的 RAM 大小和 SSD 速度,因此可能需要20–60秒。一些系统可以用 LED 指示灯指示过程的完成,例如停止闪烁。

Configuring IRST hibernation events in the Linux kernel requires CONFIG_INTEL_RST built-in or as a module. Once loaded via modprobe intel_rst, it should create the files wakeup_events and wakeup_time under /sys/bus/acpi/drivers/intel_rapid_start/*/ that can be used for further configuration. This module is tersely documented, see the source drivers/platform/x86/intel/rst.c for more details.

另请参阅英特尔快速启动技术的一般问答用户手册

故障排除[编辑 | 编辑源代码]

ACPI_OS_NAME[编辑 | 编辑源代码]

你也许需要调整你的 DSDT table 来让它工作。 参阅 DSDT 词条。

睡眠/休眠无法进行,或无法稳定进行[编辑 | 编辑源代码]

本文或本章节的事实准确性存在争议。

原因: 本节混合了几个无关的原因。(在 Talk:电源管理/挂起与休眠 中讨论)


有相当多的错误报告指出,他们的屏幕在给出可读的错误信息前就关闭了,有时屏幕关闭了,却再也无法唤醒。这些故障在笔记本电脑和台式机上都曾发生。(这不是个官方解决方案),但切换到旧的内核,尤其是LTS内核,或许可以修复这个问题。


A problem may arise when using the hardware watchdog timer (disabled by default, see RuntimeWatchdogSec= in systemd-system.conf(5) § OPTIONS). A buggy watchdog timer may reset the computer before the system finishes creating the hibernation image.

Sometimes the screen goes black due to device initialization from within the initramfs. Removing any modules you might have in Mkinitcpio#MODULES, removing the kms hook and rebuilding the initramfs can possibly solve this issue, in particular with graphics drivers for early KMS. Initializing such devices before resuming can cause inconsistencies that prevents the system resuming from hibernation. This does not affect resuming from RAM. Also, check the blog article best practices to debug suspend issues.

Moving from the ATI video driver to the newer AMDGPU driver could also help to make the hibernation and awakening process successful.

For NVIDIA users, blacklisting the module nvidiafb might help. [10]

Laptops with an Intel CPU that load the intel_lpss_pci module for a touchpad may face kernel panic on resume (blinking caps lock) [11]. The module needs to be added to initramfs as:

/etc/mkinitcpio.conf
MODULES=(... intel_lpss_pci ...)

然后重新生成initramfs


USB device errors[编辑 | 编辑源代码]

System may fail to suspend because of a USB device. You might see the following error:

PM: Some devices failed to suspend, or early wake event detected
...
xhci_hcd 0000:02:00.0: PM: failed to suspend async: error -16

lspci may give you more information on the failing device:

$ lspci -s 02:00.0
02:00.0 USB controller: Advanced Micro Devices, Inc. [AMD] 500 Series Chipset USB 3.1 XHCI Controller

Try disconnecting devices on that port.


网络唤醒(WoL, Wake-on-LAN)[编辑 | 编辑源代码]

如果网络唤醒被启用,网卡可能会消耗电力,即使电脑处于休眠状态。

挂起后被立即唤醒[编辑 | 编辑源代码]

参见电源管理/唤醒触发器#挂起后被立即唤醒

系统在休眠后没有断电[编辑 | 编辑源代码]

When you hibernate your system, the system should power off (after saving the state on the disk). On some firmware the S4 sleeping state does not work reliably. For example, instead of powering off, the system might reboot or stay on but unresponsive. If that happens, it might be instructive to set the HibernateMode to shutdown in sleep.conf.d(5):

/etc/systemd/sleep.conf.d/hibernatemode.conf
[Sleep]
HibernateMode=shutdown

With the above configuration, if everything else is set up correctly, on invocation of a systemctl hibernate the machine will shut down, saving state to disk as it does so.

休眠后启动时未找到操作系统(或启动错误的操作系统)[编辑 | 编辑源代码]

当引导磁盘是外部磁盘时,可能会发生这种情况,这似乎是由 BIOS/固件限制引起的。BIOS/固件尝试从内部磁盘启动,而休眠是从外部(或其他)磁盘上的操作系统完成的。

类似于#系统在休眠后没有断电,设置 HibernateMode=shutdown以永久解决问题。如果您已经将自己锁定在外,您可以尝试重新启动系统4次(每次等待错误出现),这在某些BIOS上强制执行正常的引导过程。

Swap file in /home[编辑 | 编辑源代码]

If the swap file is in /home/, systemd-logind will not be able to access it, giving the Call to Hibernate failed: No such file or directory warning message and resulting in a need for authentication on systemctl hibernate. This setup should be avoided, as it is considered unsupported upstream. See systemd issue 15354 for two workarounds.

PC will not wake from sleep on A520I and B550I motherboards[编辑 | 编辑源代码]

On some motherboards with A520i and B550i chipsets, the system will not completely enter the sleep state or come out of it. Symptoms include the system entering sleep and the monitor turning off while internal LEDs on the motherboard or the power LED stay on. Subsequently, the system will not come back from this state and require a hard power off. If you have similar issues with AMD, first make sure your system is fully updated and check whether the AMD microcode package is installed.

Verify the line starting with GPP0 has the enabled status:

$ cat /proc/acpi/wakeup
Device	S-state	  Status   Sysfs node
GP12	  S4	*enabled   pci:0000:00:07.1
GP13	  S4	*enabled   pci:0000:00:08.1
XHC0	  S4	*enabled   pci:0000:0b:00.3
GP30	  S4	*disabled
GP31	  S4	*disabled
PS2K	  S3	*disabled
GPP0	  S4	*enabled   pci:0000:00:01.1
GPP8	  S4	*enabled   pci:0000:00:03.1
PTXH	  S4	*enabled   pci:0000:05:00.0
PT20	  S4	*disabled
PT24	  S4	*disabled
PT26	  S4	*disabled
PT27	  S4	*disabled
PT28	  S4	*enabled   pci:0000:06:08.0
PT29	  S4	*enabled   pci:0000:06:09.0

If that is enabled, you can run the following command to disable it:

# echo GPP0 > /proc/acpi/wakeup

Now test by running systemctl suspend and let the system go to sleep. Then try to wake the system after a few seconds. If it works, you can make the workaround permanent. Create a systemd unit file:

/etc/systemd/system/toggle-gpp0-to-fix-wakeup.service
[Unit]
Description="Disable GPP0 to fix suspend issue"

[Service]
ExecStart=/bin/sh -c "/bin/echo GPP0 > /proc/acpi/wakeup"

[Install]
WantedBy=multi-user.target

Do a daemon-reload and start/enable the newly created unit.

Alternatively, you can create a udev rule. Assuming GPP0’s sysfs node is pci:0000:00:01.1 like in the example, run udevadm info -a -p /sys/bus/pci/devices/0000\:00\:01.1 to get the relevant information and create a udev rule like this one:

/etc/udev/rules.d/10-gpp0-acpi-fix.rules
KERNEL=="0000:00:01.1", SUBSYSTEM=="pci", DRIVERS=="pcieport", ATTR{vendor}=="0x1022", ATTR{device}=="0x1483", ATTR{power/wakeup}="disabled"

The udev daemon is already watching for changes in your system by default. If needed you can reload the rules manually.

Suspend from corresponding laptop Fn key not working[编辑 | 编辑源代码]

If, regardless of the setting in logind.conf, the sleep button does not work (pressing it does not even produce a message in syslog), then logind is probably not watching the keyboard device. [12] Do:

# journalctl --grep="Watching system buttons"

You might see something like this:

May 25 21:28:19 vmarch.lan systemd-logind[210]: Watching system buttons on /dev/input/event2 (Power Button)
May 25 21:28:19 vmarch.lan systemd-logind[210]: Watching system buttons on /dev/input/event3 (Sleep Button)
May 25 21:28:19 vmarch.lan systemd-logind[210]: Watching system buttons on /dev/input/event4 (Video Bus)

Notice no keyboard device. List keyboard devices as follows:

$ stat -c%N /dev/input/by-id/*-kbd
...
/dev/input/by-id/usb-SIGMACHIP_USB_Keyboard-event-kbd -> ../event6
...

Now obtain ATTRS{name} for the parent keyboard device [13]. As an example, on the above list this keyboard device has event6 as device input event, it can be used to search its respective attribute name:

# udevadm info -a /dev/input/event6
...
KERNEL=="event6"
...
ATTRS{name}=="SIGMACHIP USB Keyboard"

Now write a custom udev rule to add the "power-switch" tag:

/etc/udev/rules.d/70-power-switch-my.rules
ACTION=="remove", GOTO="power_switch_my_end"
SUBSYSTEM=="input", KERNEL=="event*", ATTRS{name}=="SIGMACHIP USB Keyboard", TAG+="power-switch"
LABEL="power_switch_my_end"

After reloading the udev rules and restarting systemd-logind.service, you should see Watching system buttons on /dev/input/event6 in the journal of logind.

System freezes for 60 seconds and then wakes back up or hangs after waking up[编辑 | 编辑源代码]

Since systemd v256, systemd freezes user.slice before sleeping. This process can fail due to kernel bugs, particularly when KVM is in use.[14][15]

Messages in the logs will contain Failed to freeze unit 'user.slice' before sleep. When such an issue occurs, trying to login (start another session) would fail with pam_systemd(process:session): Failed to create session: Job 9876 for unit 'session-6.scope' failed with 'frozen'.

To temporarily revert back to the old behavior, edit systemd-suspend.service, systemd-hibernate.service, systemd-hybrid-sleep.service, and systemd-suspend-then-hibernate.service with the following drop-in:

[Service]
Environment=SYSTEMD_SLEEP_FREEZE_USER_SESSIONS=false