I would like to use the hybrid suspend method instead of suspend when closing the lid or selecting "Suspend" from the menu.
I can imagine to change the pm-suspend script to do so automatically, but there might be a more maintainable / easier way.
This is the older method: first suspend and then wake up to hibernate after a delay (15 minutes by default). Use this with a Linux kernel before 3.6, or if you like that it does not use any power after 15 minutes any more.
Add the file /etc/pm/config.d/00-use-suspend-hybrid
:
# Always use suspend_hybrid instead of suspend
if [ "$METHOD" = "suspend" ]; then
METHOD=suspend_hybrid
fi
# The delay after which hibernation gets triggered (default: 900 seconds, 15 minutes):
PM_HIBERNATE_DELAY=900
You might want to make sure that the hybrid method is supported on your system via the following code. If it says "0" it should work:
sudo pm-is-supported --suspend-hybrid && echo $?
If you have a Linux 3.6 kernel, you can use the following, which will suspend to both disk and RAM from the beginning.
Add the file /etc/pm/config.d/00-use-suspend-hybrid
:
# WORKAROUND: always set the default hibernate mode first (normal mode)
# (not required if you have the patch mentioned by Rohan below (http://askubuntu.com/a/344879/169))
HIBERNATE_MODE=platform
# Always use hibernate instead of suspend, but with "suspend to both"
if [ "$METHOD" = "suspend" ]; then
METHOD=hibernate
HIBERNATE_MODE=suspend
fi
# Make sure to use the kernel's method, in case uswsusp is installed etc.
SLEEP_MODULE=kernel
This will always write the image to disk and then suspend to RAM, having the benefits that resuming will always be fast (as long as the battery does not run out) and that the machine will not wake up for a short time (after PM_HIBERNATE_DELAY) to hibernate for real.
The drawback is that the process takes longer (because it always hibernates to disk), and that your battery might run out in the long run (e.g. after 12 hours).
resume
argument in /etc/default/grub.conf
. Also as nvidia user I had to set nomodeset
. So resulting grub entry in my case is: GRUB_CMDLINE_LINUX_DEFAULT="nomodeset resume=UUID=uuidofswappartition"
. Don't forget grub-update
. And also some modules has to be unloaded so created file /etc/pm/config.d/00-unload_modules
with line SUSPEND_MODULES="ath5k r8169"
and just to make sure I also renamed 00-use-suspend-hybrid to 10-use-suspend-hybrid
In Ubuntu 18.04 has a new timed option. In systemd
, there is available a new mode suspend-then-hibernate
. This will start with the sleep mode and then transition to the hibernate mode after a fixed time.
In the hybrid-sleep
mode, the hibernate part gets effective only when the battery is critically low and the system shuts down.
To start using this function you need to create a file /etc/systemd/sleep.conf
with the next content:
[Sleep]
HibernateDelaySec=3600
This will go from sleep to hibernate after 1 hour of sleep. You can edit HibernateDelaySec
to change the delay to hibernate.
First, test if suspend-then-hibernate works using systemd
Open a terminal by pressing Ctrl+Alt+T and enter:
sudo systemctl suspend-then-hibernate
If it works make it permanent.
Open the file /etc/systemd/logind.conf
using your preferred editor. You will need to invoke your administrative power by sudo
, gksudo
or pkexec
to edit this file.
Find the two lines:
#HandleSuspendKey=suspend
#HandleLidSwitch=suspend
Note, These lines are commented out with #
in front of them. The suspend
is the default action. Remove the #
and change suspend
to suspend-then-hibernate
in these two lines so that they look like this:
HandleSuspendKey=suspend-then-hibernate
HandleLidSwitch=suspend-then-hibernate
Save the file. Log out and log back in or restart logind
service by the command:
systemctl restart systemd-logind.service
warning! your user session will be restarted
Source: Lid Closed Suspend then Hibernate
The solution by blueyed for Real hybrid suspending with Linux 3.6+ did not work for me. I suspect this is because Ubuntu 16.04 uses systemd
and does not use the file /etc/pm/config.d/00-use-suspend-hybrid
.
First, test if hibernate and hybrid-sleep works using systemd
Open a terminal by pressing Ctrl+Alt+T and enter:
sudo systemctl hibernate
This should get your computer to hibernate. To try hybrid-sleep, enter:
sudo systemctl hybrid-sleep
If it works make it permanent.
Open the file /etc/systemd/logind.conf
using your preferred editor. You will need to invoke your administrative power by sudo
, gksudo
or pkexec
to edit this file.
Find the two lines:
#HandleSuspendKey=suspend
#HandleLidSwitch=suspend
Note, These lines are commented out with #
in front of them. The suspend
is the default action. Remove the #
and change suspend
to hybrid-sleep
in these two lines so that they look like this:
HandleSuspendKey=hybrid-sleep
HandleLidSwitch=hybrid-sleep
Save the file. Log out and log back in.
Note:
suspend
or hybrid-sleep
there is a third option, hibernate
.Suspend
from the cog menu puts the computer to
normal suspend not hybrid-sleep.I hope this helps
In 12.04 I noticed that when hibernation is triggered (using PM_HIBERNATE_DELAY=XX
), the resume/thaw the shell scripts do not unset the grub recordfail variable. Therefore grub does not autoboot.
Timeout is set to -1 and it awaits user selection. I am guessing this requires some editing of scripts in /etc/pm/sleep.d/10_grub-common
. Am a novice so I haven't dabbled to figure out the exact change unfortunately.
This question comes up frequently enough in Google that I think it's worth bumping. The method described here is (imo) not hybrid suspend. It is "hibernate after X minutes in suspend". True hybrid suspend writes your RAM out to disk and then goes in low-power state (sleep mode). While it takes longer, the resume is instant while the machine has battery left, otherwise resumes form hard disk. This behaviour is what most people know as hybrid sleep, and used by default in the newer Windows and Mac laptops.
Here's how to enable the real hybrid suspend:
% cat /etc/pm/config.d/00-use-suspend-hybrid # Always use suspend_hybrid instead of suspend if [ "$METHOD" = "suspend" ]; then METHOD=suspend_hybrid fi
This method works for me on my Sony Vaio SVS.
PS: Reproducing the patch here in case the file is deleted in the future:
diff --git a/pm/pm-functions.in b/pm/pm-functions.in --- a/pm/pm-functions.in +++ b/pm/pm-functions.in @@ -316,8 +316,28 @@ if [ -z "$HIBERNATE_MODULE" ] && \ { [ -n "${HIBERNATE_MODE}" ] && \ grep -qw "${HIBERNATE_MODE}" /sys/power/disk && \ + HIBERNATE_MODE_SAVE=$(cat /sys/power/disk) && \ + HIBERNATE_MODE_SAVE="${HIBERNATE_MODE_SAVE##*[}" && \ + HIBERNATE_MODE_SAVE="${HIBERNATE_MODE_SAVE%%]*}" && \ echo -n "${HIBERNATE_MODE}" > /sys/power/disk echo -n "disk" > /sys/power/state + RET=$? + echo -n "$HIBERNATE_MODE_SAVE" > /sys/power/disk + return "$RET" + } +fi + +# for kernels that support suspend to both (i.e. hybrid suspend) +# since kernel 3.6 +if [ -z "$SUSPEND_HYBRID_MODULE" ] && \ + [ -f /sys/power/disk ] && \ + grep -q disk /sys/power/state && \ + grep -q suspend /sys/power/disk; then + SUSPEND_HYBRID_MODULE="kernel" + do_suspend_hybrid() + { + HIBERNATE_MODE="suspend" + do_hibernate } fi
Sources:
There's another solution without adding any file in config.d, just using wakealarm in /sys/class/rtc/rtc0. Make use obsolete code in pm-functions (/usr/lib/pm-utils) after the comments #since the kernel does not directly support ... , ('cos the current kernel (after 3.6 something) does directly support). Revert that code and put in do_suspend() part instead of do_suspend_hybrid(), and use the patch for pm-functions ('til they fix it).
Obsolete code (suspend then hibernate when suspend_hybrid is called):
# since the kernel does not directly support hybrid sleep, we do
# something else -- suspend and schedule an alarm to go into
# hibernate if we have slept long enough.
# Only do this if we do not need to do any special video hackery on resume
# from hibernate, though.
if [ -z "$SUSPEND_HYBRID_MODULE" -a -w "$PM_RTC/wakealarm" ] && \
check_suspend && check_hibernate && ! is_set $HIBERNATE_RESUME_POST_VIDEO; \
then
SUSPEND_HYBRID_MODULE="kernel"
do_suspend_hybrid() {
WAKETIME=$(( $(cat "$PM_RTC/since_epoch") + PM_HIBERNATE_DELAY))
echo >"$PM_RTC/wakealarm"
echo $WAKETIME > "$PM_RTC/wakealarm"
if do_suspend; then
NOW=$(cat "$PM_RTC/since_epoch")
if [ "$NOW" -ge "$WAKETIME" -a "$NOW" -lt $((WAKETIME + 30)) ]; then
log "Woken by RTC alarm, hibernating."
# if hibernate fails for any reason, go back to suspend.
do_hibernate || do_suspend
else
echo > "$PM_RTC/wakealarm"
fi
else
# if we cannot suspend, just try to hibernate.
do_hibernate
fi
}
fi
Recommended. Even easier to use uswsusp while the same time maximize the benefit of s2both i.e. s2both when suspend. Put the reverted code in do_suspend() part of uswsusp module (/usr/lib/pm-utils/module.d).
Reverted code (suspend_hybrid when suspend is called):
WAKETIME=$(( $(cat "$PM_RTC/since_epoch") + PM_HIBERNATE_DELAY))
echo >"$PM_RTC/wakealarm"
echo $WAKETIME > "$PM_RTC/wakealarm"
if do_suspend_hybrid; then
NOW=$(cat "$PM_RTC/since_epoch")
if [ "$NOW" -ge "$WAKETIME" -a "$NOW" -lt $((WAKETIME + 30)) ]; then
log "Woken by RTC alarm, hibernating."
# if hibernate fails for any reason, go back to suspend_hybrid.
do_hibernate || do_suspend_hybrid
else
echo > "$PM_RTC/wakealarm"
fi
else
# when do_suspend is being called, convert to suspend_hybrid.
do_suspend_hybrid
fi
With uswsusp, we can see the progress of suspend/hibernate and the reverse process displayed in text, even we can abort it by pressing backspace. Without uswsusp, suspend/hibernate just appear-disappear annoyingly, especially when wakealarm is triggered and execute hibernate (s2disk in uswsusp). Set the period of sleep before hibernate in the usual place on pm-functions file.
# variables to handle hibernate after suspend support
PM_HIBERNATE_DELAY=900 # 15 minutes
PM_RTC=/sys/class/rtc/rtc0
Here's the uswsusp mod: (remember, this module is called from pm-functions so the inserted variables are the same)
#!/bin/sh
# disable processing of 90chvt and 99video.
# s2ram and s2disk handle all this stuff internally.
uswsusp_hooks()
{
disablehook 99video "disabled by uswsusp"
}
# Since we disabled 99video, we need to take responsibility for proper
# quirk handling. s2ram handles all common video quirks internally,
# so all we have to do is translate the HAL standard options to s2ram options.
uswsusp_get_quirks()
{
OPTS=""
ACPI_SLEEP=0
for opt in $PM_CMDLINE; do
case "${opt##--quirk-}" in # just quirks, please
dpms-on) ;; # no-op
dpms-suspend) ;; # no-op
radeon-off) OPTS="$OPTS --radeontool" ;;
reset-brightness) ;; # no-op
s3-bios) ACPI_SLEEP=$(($ACPI_SLEEP + 1)) ;;
s3-mode) ACPI_SLEEP=$(($ACPI_SLEEP + 2)) ;;
vbe-post) OPTS="$OPTS --vbe_post" ;;
vbemode-restore) OPTS="$OPTS --vbe_mode" ;;
vbestate-restore) OPTS="$OPTS --vbe_save" ;;
vga-mode-3) ;; # no-op
save-pci) OPTS="$OPTS --pci_save" ;;
none) QUIRK_NONE="true" ;;
*) continue ;;
esac
done
[ $ACPI_SLEEP -ne 0 ] && OPTS="$OPTS --acpi_sleep $ACPI_SLEEP"
# if we were told to ignore quirks, do so.
# This is arguably not the best way to do things, but...
[ "$QUIRK_NONE" = "true" ] && OPTS=""
}
# Since we disabled 99video, we also need to handle displaying
# help info for the quirks we handle.
uswsusp_help()
{
echo # first echo makes it look nicer.
echo "s2ram video quirk handler options:"
echo
echo " --quirk-radeon-off"
echo " --quirk-s3-bios"
echo " --quirk-s3-mode"
echo " --quirk-vbe-post"
echo " --quirk-vbemode-restore"
echo " --quirk-vbestate-restore"
echo " --quirk-save-pci"
echo " --quirk-none"
}
# This idiom is used for all sleep methods. Only declare the actual
# do_ method if:
# 1: some other sleep module has not already done so, and
# 2: this sleep method can actually work on this system.
#
# For suspend, if SUSPEND_MODULE is set then something else has already
# implemented do_suspend. We could just check to see of do_suspend was
# already declared using command_exists, but using a dedicated environment
# variable makes it easier to debug when we have to know what sleep module
# ended up claiming ownership of a given sleep method.
if [ -z "$SUSPEND_MODULE" ] && command_exists s2ram && \
( grep -q mem /sys/power/state || \
( [ -c /dev/pmu ] && check_suspend_pmu; ); ); then
SUSPEND_MODULE="uswsusp"
do_suspend()
{
WAKETIME=$(( $(cat "$PM_RTC/since_epoch") + PM_HIBERNATE_DELAY))
echo >"$PM_RTC/wakealarm"
echo $WAKETIME > "$PM_RTC/wakealarm"
if do_suspend_hybrid; then
NOW=$(cat "$PM_RTC/since_epoch")
if [ "$NOW" -ge "$WAKETIME" -a "$NOW" -lt $((WAKETIME + 30)) ]; then
log "Woken by RTC alarm, hibernating."
# if hibernate fails for any reason, go back to suspend_hybrid.
do_hibernate || do_suspend_hybrid
else
echo > "$PM_RTC/wakealarm"
fi
else
# when do_suspend is being called, convert to suspend_hybrid.
do_suspend_hybrid
fi
}
fi
if [ -z "$HIBERNATE_MODULE" ] && \
[ -f /sys/power/disk ] && \
grep -q disk /sys/power/state && \
[ -c /dev/snapshot ] &&
command_exists s2disk; then
HIBERNATE_MODULE="uswsusp"
do_hibernate()
{
s2disk
}
fi
if [ -z "$SUSPEND_HYBRID_MODULE" ] &&
grep -q mem /sys/power/state && \
command_exists s2both && \
check_hibernate; then
SUSPEND_HYBRID_MODULE="uswsusp"
do_suspend_hybrid()
{
uswsusp_get_quirks
s2both --force $OPTS
}
if [ "$METHOD" = "suspend_hybrid" ]; then
add_before_hooks uswsusp_hooks
add_module_help uswsusp_help
fi
fi
The answer by user68186 for Ubuntu 16.04 did not work for me. However, the solution here did.
First, ensure hibernation works. Then
Search for and install dconf Editor in Ubuntu Software. Then launch it and navigate to org -> gnome -> settings daemon -> plugins -> power.
Change the value of “lid-close-ac-action” and “lid-close-battery-action”.
In my power settings, these options show up as blank, but they work as intended.
In Ubuntu 18.04 it much more easer. In systemd is availiable a new mode suspend-then-hibernate. To start using this function you need to create a file /etc/systemd/sleep.conf with the next content:
[Sleep]
HibernateDelaySec=3600
Then you can test it by command:
sudo systemctl suspend-then-hibernate
(you can edit HibernateDelaySec to reduce delay to hibernate). If all works fine you can change Lid Close Action, to do it you need to edit the file /etc/systemd/logind.conf
You need to find option HandleLidSwitch=, uncomment it and change to HandleLidSwitch=suspend-then-hibernate. Then you need to restart logind service(wirning! you user session will be restarted) by the next command:
systemctl restart systemd-logind.service
Thats all! Now you can use this nice function.
Just add this 2 lines to /etc/systemd/sleep.conf
:
SuspendMode=suspend
SuspendState=disk