有多種方法可用於掛起,特別是:
- Suspend to idle(掛起到空閒狀態)
- 英特爾稱之為 S0ix,微軟稱之為現代待機(以前是「保持網絡連接的待機」),內核稱之為 S2Idle。設計用於替代 S3 睡眠狀態的支持系統,提供相同的節能,但大大減少了喚醒時間。
- Suspend to RAM(掛起到內存,通稱掛起)
- ACPI 定義的 S3 睡眠狀態。通過將機器中大多數和 RAM 不相關的部件斷電來工作,RAM 是恢復機器狀態所必需的。由於可以節省大量電力,建議筆記本電腦在使用電池運行且蓋子關閉時(或用戶在一段時間內處於非活動狀態)自動進入此模式。
- Suspend to disk(掛起到硬碟,通稱休眠)
- ACPI 定義的 S4 睡眠狀態。將機器狀態保存到交換空間並關閉機器。再次開機後,恢復狀態。直到開機前,機器都不會有任何待機功耗。
- Hybrid suspend(混合掛起)
- 掛起和休眠的混合,有時稱為掛起到兩者。將機器狀態保存到交換空間,但並不關閉電腦,而是調用默認的掛起機制,從而使未掉電的電腦能立刻恢復。如果電腦掉電(斷電且電池耗盡),系統也可以從硬碟的交換空間中恢復,儘管比從內存中恢復慢一些。
以上三者均由內核提供基礎功能,再由高級接口進行了一定調整,以適配一些較為複雜的硬體與內核模塊(如顯卡喚醒後的重新初始化)
內核接口 (swsusp)
可以通過直接告知內核中的軟體掛起代碼(swsusp)進入掛起狀態,具體的方法和狀態取決於硬體支持的程度。在現代內核中,向 /sys/power/state
寫入特定字符串是觸發此掛起的主要機制。
更多信息詳見內核文檔。
高級接口 (systemd)
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 sleep
命令自動選擇最合適的睡眠操作。默認情況下,使用 suspend-then-hibernate
,如果不支持則回退到 suspend
和 hibernate
。更多信息請參見 systemctl(1)。關於配置睡眠或休眠鉤子,詳見電源管理#睡眠鉤子。又見 systemctl(1)、systemd-sleep(8) 和 systemd.special(7)。
更改掛起方法
在 S0ix 掛起不能提供與常規 S3 睡眠相同的節能的系統上,或者當節能優於快速的恢復時間時,可以更改默認掛起方法。
運行以下命令以查看硬體公開支持的所有掛起方法(當前方法包裹在方括號中顯示[1]):
$ cat /sys/power/mem_sleep
[s2idle] shallow deep
mem_sleep 字符串 | 睡眠狀態 |
---|---|
s2idle | suspend-to-idle |
shallow | standby |
deep | suspend-to-RAM |
如果你的硬體沒有公布 deep
睡眠狀態,請首先檢查 UEFI 是否公布了它的某些設置,通常是在「電源(Power)」或「睡眠狀態(Sleep state)」或類似的用詞下,並使用名為 Windows 10, Windows and Linux 或 S3/Modern standby support 關於 S0ix 的選項,以及 Legacy, Linux, Linux S3 或 S3 enabled 關於 S3 睡眠的選項。否則,你可以繼續使用 s2idle
,考慮使用休眠或嘗試給 DSDT 表打補丁(或在線查找補丁版本)。
通過在更改睡眠方法後測試幾個睡眠周期,驗證你的硬體沒有 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
休眠
為了使用休眠功能,你必須創建一個 swap 分區或文件、#配置 initramfs 以便在早期用戶空間啟動恢復過程,並指定交換空間的位置以便 initramfs 可以訪問,例如:由 systemd 定義的 HibernateLocation
EFI 變量或 resume=
內核參數。下面詳細描述了這三個步驟。
- 使用 encryption 時,請參閱 dm-crypt/Swap encryption#With suspend-to-disk support。
- linux-hardened包 不支持休眠,請參閱 FS#63648。
- 即使 zram 配置了永久存儲上的後端設備,也不支持休眠到 zram 上的交換分區。雖然 logind 會阻止嘗試將休眠到 zram 上的交換空間,但作為替代,你可以創建多個交換空間。內存將存儲到交換文件中,而另一個可用交換空間將保留給 zram。有關詳細信息,請參閱 #Maintaining swap file for hibernation with zram。
swap分區/文件的大小
即使交換分區比內存小,成功休眠的可能性仍然不小。參見內核文檔中的「image_size」部分以獲取關於 image_size
sysfs(5) 偽文件的更多信息。
你可以減小 /sys/power/image_size
的設定值以使休眠鏡像儘可能小(對於小交換分區),或者增大它以加快休眠過程(也許)。對於 RAM 很大的系統,較小的值可能會顯著提高系統從休眠中恢復的速度。Systemd#systemd-tmpfiles_-_臨時文件可以用於固定你的修改。
/etc/tmpfiles.d/hibernation_image_size.conf
# Path Mode UID GID Age Argument w /sys/power/image_size - - - - 0
休眠鏡像不能跨多個交換分區和/或交換文件。它必須完全適配一個交換分區或一個交換文件[2]
配置 initramfs
- 當使用一個 busybox-based 的 initramfs 時(這是默認值),
/etc/mkinitcpio.conf
中需要resume
鉤子。無論是通過卷標還是通過 UUID,交換分區都是通過 udev 設備節點來引用的,因此resume
鉤子必須在udev
鉤子之後。這是一個使用默認鉤子配置的示例:
HOOKS=(base udev autodetect microcode modconf kms keyboard keymap consolefont block filesystems resume fsck)
- 編輯後記得重新生成 initramfs。
- 當使用帶有
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=
內核參數指定交換文件的物理偏移量。 [3]
在除 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
。
或者,為了直接獲取偏移量:
# filefrag -v swap_file | awk '$1=="0:" {print substr($4, 1, length($4)-2)}'
對於 Btrfs,請不要嘗試使用 filefrag 工具,因為 filefrag 獲取到的「物理」偏移量並不是真正在硬碟上的偏移量;這是一個虛擬的硬碟地址空間,用於支持多設備[4]。請使用 btrfs-inspect-internal(8) 命令作為代替,例如:
# btrfs inspect-internal map-swapfile -r swap_file
198122980
在本例中,設置偏移量的內核參數是 resume_offset=198122980
。
為使該更改立刻生效(無需重啟),使用 echo
將偏移量改動至 /sys/power/resume_offset
。例如,如果偏移量是38912
:
# echo 38912 > /sys/power/resume_offset
findmnt -no UUID -T swap_file
resume
參數必須指向交換文件所在的已解鎖或映射的設備。更改休眠鏡像的壓縮算法
從 Linux 6.9 開始[5],可以更改休眠鏡像的壓縮算法。默認的壓縮算法基於編譯時選項 CONFIG_HIBERNATION_DEF_COMP
選擇,但可以在啟動時和運行時覆蓋。
不同的壓縮算法具有不同的特性,休眠可能會受益於使用其中任何一種算法,尤其是當次要算法(LZ4)在默認算法(LZO)上提供更好的解壓縮速度時,這反過來會減少休眠鏡像的恢復時間。
你可以通過兩種方式覆蓋默認算法:
1) 傳遞 hibernate.compressor
作為 內核參數:
hibernate.compressor=lzo hibernate.compressor=lz4
2) 在運行時指定算法:
# echo lzo > /sys/module/hibernate/parameters/compressor # echo lz4 > /sys/module/hibernate/parameters/compressor
目前 lzo
和 lz4
是支持的算法,LZO 是默認算法。
使用 zram 維護休眠的交換文件
通過同時維護兩個或更多的交換空間,可以解決使用 zram 僅內存交換時的休眠問題。systemd 在觸發休眠前會始終忽略 zram 塊設備 [6],因此保持兩個交換空間啟用應該可以在無需進一步干預的情況下正常工作。
在配置交換文件後,請按照 zram 頁面的說明進行操作。確保 zram 具有更高的交換優先級(例如 pri=100
)。
- 不要為休眠創建按需交換單元,因為這不被官方支持。請參閱 systemd 問題 #16708 和 #30083。
- 內核單獨負責回收頁面的匿名內存並進行交換;不使用交換空間實際上可能導致內存使用不良。用戶可以通過 control groups 中的
memory.low
來管理某些應用程式的內存回收優先級。總的來說,這比設置 swappiness 參數更有效。 - 閱讀 內核文檔中的交換管理 和 Chris Down 的文章 - 為交換辯護:常見誤解 以獲取更多詳細信息。
休眠到精簡配置的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%
禁用 zswap 寫回以僅將交換空間用於休眠
在 Linux 6.8 中,zswap 增加了 一個按 cgroup 禁用寫回的選項。通過在所有可能的單元類型中使用 systemd 單元設置 MemoryZSwapWriteback
(參見 systemd.resource-control(5) § Memory Accounting and Control),可以有效地完全禁用 zswap 寫回。這使得 zswap 可以像 zram 一樣使用,同時還支持休眠。
為了避免手動創建十二個頂級按類型的 drop-in 文件(用於系統和用戶的 scope
、service
、slice
、socket
、mount
、swap
單元類型),請 安裝 zswap-disable-writebackAUR。啟用 zswap 並重新啟動以使設置生效。
嘗試執行內存密集型任務並確認 zswap 沒有將任何內容寫入磁碟:
# cat /sys/kernel/debug/zswap/written_back_pages
0
睡眠鉤子
自定義 systemd 單元
systemd 會分別為每個睡眠狀態啟動 suspend.target
、hibernate.target
、hybrid-sleep.target
或 suspend-then-hibernate.target
。所有上述目標都會拉取 sleep.target
。可以使用這些目標中的任何一個來在掛起/休眠之前或之後調用自定義單元。應為用戶操作和 root/系統操作分別創建文件。示例:
/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 hibernate.target [Service] User=%I Type=simple ExecStart=/usr/local/bin/ssh-connect.sh [Install] WantedBy=suspend.target hibernate.target
啟用 user-suspend@user.service
和/或 user-resume@user.service
以使更改生效。
ExecStartPost=/usr/bin/sleep 1
添加一個小延遲有助於防止這種情況。對於 root/系統操作:
/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 hibernate.target [Service] Type=simple ExecStart=/usr/bin/systemctl restart mnt-media.automount [Install] WantedBy=suspend.target hibernate.target
組合睡眠/恢復單元
使用組合單元文件,單個鉤子可以為不同的階段(睡眠/恢復)和不同的目標完成所有工作。
示例和解釋:
/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
:啟動後,服務被視為活動狀態,直到顯式停止。 -
StopWhenUnneeded=yes
:當活動時,如果沒有其他活動服務需要它,服務將被停止。在這個特定示例中,它將在sleep.target
停止後被停止。 - 因為
sleep.target
有StopWhenUnneeded=yes
,所以鉤子保證會為不同的任務正確啟動/停止。
位於 /usr/lib/systemd/system-sleep 的鉤子
systemd-sleep 會運行 /usr/lib/systemd/system-sleep/
中的所有可執行文件,並向每個文件傳遞兩個參數:
- 要麼是
pre
,要麼是post
,取決於機器是進入睡眠還是喚醒。 -
suspend
、hibernate
、hybrid-sleep
或suspend-then-hibernate
,取決於正在調用的是哪個。
任何自定義腳本的輸出都將由 systemd-suspend.service、systemd-hibernate.service 或 systemd-hybrid-sleep.service 記錄。你可以在 systemd's journalctl 中查看其輸出:
# journalctl -b -u systemd-suspend.service
自定義睡眠腳本的示例:
/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
不要忘記使你的腳本可執行。
一個名為 SYSTEMD_SLEEP_ACTION
的環境變量將被設置,並包含正在處理的睡眠操作。這對於 suspend-then-hibernate 特別有用,其中變量的值將是 suspend
、hibernate
或 suspend-after-failed-hibernate
(在休眠失敗的情況下)。
提示與技巧
在受信任的位置自動解鎖
在恢復時,如果系統連接到某些設備或受信任的 Wi-Fi 網絡,你可以自動解鎖系統。
/etc/local-scripts/resume-unlock.sh
#!/usr/bin/bash # 如果在受信任的位置,則解鎖會話 function trusted() { # 檢查是否連接到受信任的 Wi-Fi 網絡 [[ $(iwgetid -r) == your_home_ssid ]] \ && return 0 # 檢查是否連接了受信任的 USB 設備。 #lsusb -d xxxx:xxxx && return 0 return 1 # 不受信任 } for (( i=0; i < 10; i++ )); do if trusted; then loginctl unlock-sessions exit fi sleep 0.5 done
配置你的桌面環境,使其在恢復時鎖定,然後創建一個睡眠鉤子,在恢復後運行上述腳本。你還需要安裝 wireless_tools包 以讀取連接的 Wi-Fi SSID。如果你還想測試連接的 USB 設備,請取消腳本中的 lsusb -d ...
行的注釋,並填寫你受信任設備的 ID。你可以通過運行 lsusb
獲取設備的 ID。
完全禁用睡眠
當使用設備作為伺服器時,可能不需要或甚至不希望掛起/休眠。可以通過 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 大小相等的未格式化分區。
但是,如果你打算擦除並重新分區整個驅動器(或者已經這樣做了),那麼如果你也計劃使用該技術,則必須重新創建IRST分區。這可以通過創建一個與系統 RAM 大小相等的空分區,並將其分區類型設置為 GUID D3BFE2DE-3DAF-11DF-BA40-E3A556D89593
(對於 GPT 分區)或 ID 0x84
(對於 MBR 分區)來實現。你可能還需要在系統的固件設置中啟用對IRST的支持。
IRST 休眠過程的持續時間(即將RAM的全部內容複製到特殊分區)取決於系統的 RAM 大小和 SSD 速度,因此可能需要20–60秒。一些系統可以用 LED 指示燈指示過程的完成,例如停止閃爍。
在 Linux 內核中配置 IRST 休眠事件需要 CONFIG_INTEL_RST
內置或作為模塊。一旦通過 modprobe intel_rst
加載,它應該在 /sys/bus/acpi/drivers/intel_rapid_start/*/
下創建 wakeup_events
和 wakeup_time
文件,這些文件可用於進一步配置。該模塊的文檔較少,請參閱原始碼 drivers/platform/x86/intel/rst.c 以獲取更多詳細信息。
跟蹤筆記本電腦電池在睡眠狀態下的能量變化
要測量掛起狀態下的功耗,請使用 Batenergy 腳本將電池變化記錄到系統日誌中。這允許比較 S3 / S0x 狀態下的功耗,或在 BIOS 和內核更新後檢查回歸和修復。該腳本需要安裝 bc包 進行計算。
故障排除
ACPI_OS_NAME
你也許需要調整你的 DSDT table 來讓它工作。參閱 DSDT 詞條。
睡眠/休眠無法進行,或無法穩定進行
有相當多的錯誤報告指出,他們的屏幕在給出可讀的錯誤信息前就關閉了,有時屏幕關閉了,卻再也無法喚醒。這些故障在筆記本電腦和台式機上都曾發生。這不是個官方解決方案,但切換到舊的內核,尤其是LTS內核,或許可以修復這個問題。
使用硬體看門狗定時器(默認禁用,參見RuntimeWatchdogSec=
in systemd-system.conf(5) § OPTIONS)時可能會出現一個問題。一個有問題的看門狗定時器可能會在系統完成創建休眠映像之前重置計算機。
有時屏幕會變黑,這是由於從initramfs內部初始化設備引起的。移除Mkinitcpio#MODULES中可能包含的任何模塊,移除kms
鉤子並重新生成initramfs可能會解決這個問題,特別是對於早期KMS的圖形驅動程序。在恢復之前初始化這些設備可能會導致系統無法從休眠中恢復的不一致情況。這不影響從RAM中恢復。此外,請查看博客文章調試掛起問題的最佳實踐。
從ATI視頻驅動程序切換到較新的AMDGPU驅動程序也可能有助於使休眠和喚醒過程成功。
對於NVIDIA用戶,禁用模塊nvidiafb
可能會有所幫助。[8]
帶有Intel CPU的筆記本電腦如果加載了intel_lpss_pci
模塊用於觸摸板,可能會在恢復時遇到內核恐慌(大寫鎖定鍵閃爍)[9]。需要將該模塊添加到initramfs中:
/etc/mkinitcpio.conf
MODULES=(... intel_lpss_pci ...)
USB 設備錯誤
系統可能因為USB設備而無法掛起。你可能會看到以下錯誤:
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可能會給你更多關於故障設備的信息:
$ lspci -s 02:00.0
02:00.0 USB controller: Advanced Micro Devices, Inc. [AMD] 500 Series Chipset USB 3.1 XHCI Controller
嘗試斷開該埠上的設備。
網絡喚醒(WoL, Wake-on-LAN)
如果網絡喚醒被啟用,網卡可能會消耗電力,即使電腦處於休眠狀態。
掛起後被立即喚醒
系統在休眠後沒有斷電
當你休眠系統時,系統應該會斷電(在將狀態保存到磁碟後)。在某些固件上,S4 睡眠狀態可能無法可靠工作。例如,系統可能會重啟或保持開啟但無響應,而不是斷電。如果發生這種情況,可以在 sleep.conf.d(5) 中將 HibernateMode
設置為 shutdown
:
/etc/systemd/sleep.conf.d/hibernatemode.conf
[Sleep] HibernateMode=shutdown
使用上述配置,如果其他設置都正確,在調用 systemctl hibernate
時,機器將會關閉,並在關閉過程中將狀態保存到磁碟。
休眠後啟動時未找到作業系統(或啟動錯誤的作業系統)
當引導磁碟是外部磁碟時,可能會發生這種情況,這似乎是由 BIOS/固件限制引起的。BIOS/固件嘗試從內部磁碟啟動,而休眠是從外部(或其他)磁碟上的作業系統完成的。
類似於#系統在休眠後沒有斷電,設置 HibernateMode=shutdown
以永久解決問題。如果你已經將自己鎖定在外,你可以嘗試重新啟動系統4次(每次等待錯誤出現),這在某些BIOS上強制執行正常的引導過程。
Swap file in /home
如果交換文件位於 /home/
目錄下,systemd-logind 將無法訪問它,從而導致 Call to Hibernate failed: No such file or directory
警告信息,並且在執行 systemctl hibernate
時需要身份驗證。應避免這種設置,因為它被認為是 上游不支持的。有關兩種解決方法,請參閱 systemd issue 15354。
PC 無法從 A520I 和 B550I 主板的睡眠中喚醒
在某些使用 A520i 和 B550i 晶片組的主板上,系統無法完全進入睡眠狀態或從睡眠狀態中恢復。症狀包括系統進入睡眠狀態,顯示器關閉,但主板上的內部 LED 或電源 LED 仍然亮著。隨後,系統無法從該狀態恢復,需要強制關機。如果你在使用 AMD 時遇到類似問題,請首先確保你的系統已完全更新,並檢查是否安裝了 AMD microcode 軟體包。
驗證以 GPP0
開頭的行是否處於啟用狀態:
$ 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
如果該行已啟用,你可以運行以下命令禁用它:
# echo GPP0 > /proc/acpi/wakeup
現在通過運行 systemctl suspend
進行測試,讓系統進入睡眠狀態。然後嘗試在幾秒鐘後喚醒系統。如果有效,你可以使此解決方法永久生效。創建一個 systemd 單元文件:
/etc/systemd/system/toggle-gpp0-to-fix-wakeup.service
[Unit] Description="禁用 GPP0 以修復睡眠問題" [Service] ExecStart=/bin/sh -c "/bin/echo GPP0 > /proc/acpi/wakeup" [Install] WantedBy=multi-user.target
執行 daemon-reload 並 start/enable 新創建的單元。
或者,你可以創建一個 udev 規則。假設 GPP0
的 sysfs 節點為 pci:0000:00:01.1
,如示例所示,運行 udevadm info -a -p /sys/bus/pci/devices/0000\:00\:01.1
以獲取相關信息,並創建如下 udev 規則:
/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"
默認情況下,udev 守護程序已經在監視系統中的更改。如果需要,你可以 手動重新加載規則。
Suspend from corresponding laptop Fn key not working
如果無論 `logind.conf` 中的設置如何,睡眠按鈕都不起作用(按下它甚至不會在 `syslog` 中產生消息),那麼 `logind` 可能沒有監視鍵盤設備。[10] 請執行以下操作:
# journalctl --grep="Watching system buttons"
你可能會看到類似以下的內容:
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)
注意沒有鍵盤設備。按如下方式列出鍵盤設備:
$ stat -c%N /dev/input/by-id/*-kbd
... /dev/input/by-id/usb-SIGMACHIP_USB_Keyboard-event-kbd -> ../event6 ...
現在獲取父鍵盤設備的 ATTRS{name}
[11]。例如,在上面的列表中,此鍵盤設備的設備輸入事件為 event6
,可以用於搜索其相應的屬性名稱:
# udevadm info -a /dev/input/event6
... KERNEL=="event6" ... ATTRS{name}=="SIGMACHIP USB Keyboard"
現在編寫一個自定義的 `udev` 規則來添加 "power-switch" 標籤:
/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"
在 重新加載 udev 規則 並 重啟 systemd-logind.service
後,你應該會在 `logind` 的日誌中看到 Watching system buttons on /dev/input/event6
。
System freezes for 60 seconds and then wakes back up or hangs after waking up
自 systemd v256 起,systemd 在休眠前會凍結 user.slice
。由於內核錯誤,特別是當使用 KVM 時,此過程可能會失敗。[12][13]
日誌中的消息會在休眠前包含 Failed to freeze unit 'user.slice'
。當發生此類問題時,嘗試登錄(啟動另一個會話)將失敗,並顯示:
pam_systemd(process:session): Failed to create session: Job 9876 for unit 'session-6.scope' failed with 'frozen'
要暫時恢復舊行為,請edit systemd-suspend.service
、systemd-hibernate.service
、systemd-hybrid-sleep.service
和 systemd-suspend-then-hibernate.service
,並添加以下 drop-in:
[Service] Environment=SYSTEMD_SLEEP_FREEZE_USER_SESSIONS=false