電源管理/掛起與休眠
有多種方法可用於掛起,特別是:
- 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(1)、systemd-sleep(8) 和 systemd.special(7)。
更改掛起方法[編輯 | 編輯原始碼]
在 S0ix 掛起不能提供與常規 S3 睡眠相同的節能的系統上,或者當節能優於快速的恢復時間時,可以更改默認掛起方法。
運行以下命令以查看硬體公開支持的所有掛起方法(當前方法包裹在方括號中顯示[2]):
$ 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分區/文件的大小[編輯 | 編輯原始碼]
即使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。
- 當使用帶有
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
findmnt -no UUID -T swap_file
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[編輯 | 編輯原始碼]
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
).
- Do not create an on-demand swap unit for hibernation as it is not officially supported. See systemd issues #16708 and #30083.
- The kernel alone is responsible for reclaiming anonymous memory of pages and swapping them; not using a swap space can actually lead to bad memory usage. The user can manage priorities in reclaiming memory for certain applications in the form of
memory.low
, tunable by control groups. Overall this is more effective than setting the swappiness parameter. - Read the Swap Management in kernel documentation and the Chris Down's article - In defence of swap: common misconceptions for more details.
休眠到精簡配置的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%
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.
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 aftersleep.target
is stopped.- Because
sleep.target
hasStopWhenUnneeded=yes
, the hook is guaranteed to start/stop properly for different tasks.
Hooks in /usr/lib/systemd/system-sleep[編輯 | 編輯原始碼]
systemd-sleep runs all executables in /usr/lib/systemd/system-sleep/
, passing two arguments to each of them:
- Either
pre
orpost
, depending on whether the machine is going to sleep or waking up. suspend
,hibernate
orhybrid-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 大小相等的未格式化分區。
但是,如果您打算擦除並重新分區整個驅動器(或者已經這樣做了),那麼如果您也計劃使用該技術,則必須重新創建IRST分區。這可以通過創建一個與系統 RAM 大小相等的空分區,並將其分區類型設置為 GUID D3BFE2DE-3DAF-11DF-BA40-E3A556D89593
(對於 GPT 分區)或 ID 0x84
(對於 MBR 分區)來實現。您可能還需要在系統的固件設置中啟用對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 詞條。
睡眠/休眠無法進行,或無法穩定進行[編輯 | 編輯原始碼]
有相當多的錯誤報告指出,他們的屏幕在給出可讀的錯誤信息前就關閉了,有時屏幕關閉了,卻再也無法喚醒。這些故障在筆記本電腦和台式機上都曾發生。(這不是個官方解決方案),但切換到舊的內核,尤其是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 ...)
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