跳至內容

電源管理/掛起與休眠

出自 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