I have never been able to make hibernation (suspend to disk) work on my laptops (Dell M3800 and Dell XPS 13 9370) on Ubuntu with systemd. The symptom was that running
1 |
sudo systemctl hibernate |
was making the system shutdown, but then upon restart the system was not restored: it was just like booting the system from scratch.
I had also tried with uswsusp (which is installed if you install the package hibernate), with its program s2disk, but I experienced many problems: it wasn’t working reliably and it was making booting (even standard booting) much longer (several seconds more).
Then, after looking at several blog posts, I found that the solution is rather simple, and I’ll detail the steps here. I’ll also show how to use suspend-then-hibernate.
First, you need to have swap already setup, e.g., a swap partition (though I think a swap file would work as well, but in that case the configuration is slightly more complex). For example in /etc/fstab you should have something like
1 2 |
# swap was on /dev/<your swap partition> during installation UUID=<the UUID of your swap partition> none swap sw 0 0 |
The UUID is important and you should take note of it.
How big should the swap be? You can find some hints here: https://help.ubuntu.com/community/SwapFaq. I have 16Gb of RAM and my swap partition is 20 Gb.
Then, you must make sure initramfs is “aware” of your swap partition and that it is already able to “resume” from that. This should already be the case but you can try to run
1 |
sudo update-initramfs -u |
and after some time you should see something like:
1 2 3 4 |
update-initramfs: Generating /boot/initrd.img-<your current kernel version> I: The initramfs will attempt to resume from /dev/<your swap partition> I: (UUID=<the UUID of your swap partition>) I: Set the RESUME variable to override this. |
The UUID must be the same as your swap UUID in the /etc/fstab.
Now, it’s just a matter of editing your /etc/default/grub and make sure you specify resume in GRUB_CMDLINE_LINUX_DEFAULT, with the UUID of your swap partition. So it should be something like (remember that <UUID of your swap partition> must be replaced with the UUID):
1 |
GRUB_CMDLINE_LINUX_DEFAULT="quiet splash resume=UUID=<UUID of your swap partition>" |
Save the file and update grub:
1 |
sudo update-grub |
Reboot the system and now try to hibernate again (first you might want to start a few applications so that you’re sure that the system is effectively restored to the same state):
1 |
sudo systemctl hibernate |
Wait for the system to shut down and switch it on again. The splash screen should tell you something about that it is “resuming from <your swap partition>”. If all goes well you’ll have to enter your password to unlock the system which you should find in the state you left it before hibernating! 🙂
suspend-then-hibernate
Another interesting mechanism provided by systemd is suspend-then-hibernate: the system is suspended (to RAM) and after some time it is hibernated (suspended to disk).
The amount of time before hibernating is defined in the file /etc/systemd/sleep.conf. Let’s have a look at the default contents:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 |
# This file is part of systemd. # # systemd is free software; you can redistribute it and/or modify it # under the terms of the GNU Lesser General Public License as published by # the Free Software Foundation; either version 2.1 of the License, or # (at your option) any later version. # # Entries in this file show the compile time defaults. # You can change settings by editing this file. # Defaults can be restored by simply deleting this file. # # See systemd-sleep.conf(5) for details [Sleep] #AllowSuspend=yes #AllowHibernation=yes #AllowSuspendThenHibernate=yes #AllowHybridSleep=yes #SuspendMode= #SuspendState=mem standby freeze #HibernateMode=platform shutdown #HibernateState=disk #HybridSleepMode=suspend platform shutdown #HybridSleepState=disk #HibernateDelaySec=180min |
By default everything is commented out, but the values, as stated at the beginning of the file, represent the default values. So you can see that suspend-then-hibernate is enabled and that the default delay time before hibernating is 180 minutes. If you’re not happy with that value, uncomment the line and change the value. For example, I set it to 10 minutes:
1 |
HibernateDelaySec=10min |
You can now test this functionality with this command:
1 |
sudo systemctl suspend-then-hibernate |
The system will suspend to RAM and if you don’t touch the computer after 10 minutes you can hear some sounds: the system will effectively hibernate.
If you want to make this mechanisms the default suspend mechanism, e.g., you close the lid and the system will suspend and then after some time it will hibernate, you CANNOT set the value of SuspendMode in the file above, since that has another meaning. To make suspend-then-hibernate the default suspend mechanism you have to create this symlink:
1 2 |
sudo ln -s /usr/lib/systemd/system/systemd-suspend-then-hibernate.service \ /etc/systemd/system/systemd-suspend.service |
No need to restart, try to close the lid and the laptop will suspend, after 10 minutes it will hibernate.
Please, keep in mind that the above command will completely replace the behavior of suspend.
If you want to have a finer grain control, you might want to edit the file /etc/systemd/logind.conf, in particular uncomment and set the entries (then you’ll have to restart or restart the systemd-logind.service service):
1 2 3 4 5 6 |
#HandlePowerKey=poweroff #HandleSuspendKey=suspend #HandleHibernateKey=hibernate #HandleLidSwitch=suspend #HandleLidSwitchExternalPower=suspend #HandleLidSwitchDocked=ignore |
which should be self-explicative, but I haven’t tested this approach.
Happy hibernating 🙂