I’ve had this question a few times, so it’s probably a good candidate for my blog.
If you want to do something before you suspend, like unload a module or run some script, it’s quite easy with systemd. Similarly, you can easily do something when the system resumes (like reload the module).
The details are in the systemd-suspend man page:
man systemd-suspend.service
Simply put an executable script of any name under /usr/lib/systemd/system-sleep/ that checks whether the first argument is pre (for before the system suspends) or post (after the system wakes from suspend).
If it is pre, then do the thing you want to before suspend, if it’s post then do the thing you want to do after resume. Simple!
Here’s a useless example:
#!/bin/sh
if [ "${1}" == "pre" ]; then
# Do the thing you want before suspend here, e.g.:
echo "we are suspending at $(date)..." > /tmp/systemd_suspend_test
elif [ "${1}" == "post" ]; then
# Do the thing you want after resume here, e.g.:
echo "...and we are back from $(date)" >> /tmp/systemd_suspend_test
fi
27 thoughts on “Running scripts before and after suspend with systemd”
Other users of Debian might want to take notice that the path to place the files under for that distribution is /lib/systemd/system-sleep/, i.e. without the initial /usr. Although this actually is properly documented with the correct path in the man page, it is a detail which is easy to miss.
Thanks for mentioning this.
Thank you, this helped me a lot!
I actually expected lots of hacking but it’s just a systemd thing.
Still, saved me a lot of manpage digging!
Worked on Fedora with systemd!
Great!
Thanks, now my keyboard backlight settings get saved and restored correctly on suspend/resume 🙂
I wanted to make a backup to my server before suspend, but find that the network is shut down before my “pre-script” is executed.
A solution appears quite complicated:
https://unix.stackexchange.com/questions/337853/how-can-i-trigger-a-systemd-unit-on-suspend-before-networking-is-shut-down
Any other solution?
Hi Klaus,
I haven’t tested that, but it looks like by the time you get to running the script as per my blog, the suspend process has already begun which has taken out your networking service.
The solution looks complicated, but basically it’s just a systemd service file which does something just before suspend. For you, that could be the server backup. Keep in mind though that even if you did this, there are timeouts you’ll need to contend with. Also, it seems to me that you won’t get any visibility into the backup (did it really finish before your system was suspended?).
Is there a reason you have to do your backup before suspend? Can you just run backups on an hourly cronjob or something? If you’re using rsync (or rsnapshot) then you’ll just send the differences anyway.
-c
Hi Chris,
Thanks for your answer and thanks for the good work.
You are right that crontab is a way to go, though I would prefer to back-up automatically, when I am finished working and closing down.
(combined with ad-hoc backups).
With respect to timeouts etc. my plan was to make a check at restart.
Yes, I am using rsync and it is working perfect, but since it is often remotely (ssh+internet) it can be slow and time consuming and annoying while doing other work.(Thunderbird is a bad choice in that respect, since even small changes can cause large files to be sync’ed).
Hi,
Thanks for the example code!
I’ve just started using Linux and I’ve been pulling my hair over my tuner card crashing after suspend, but now I’m finally able to unload Tvheadend and my TV tuner driver before suspend and restart them after suspend.
I had to make a small adjustment to the script, since I got an error “unexpected operator” in the if-statements.
Before if [ “${1}” == “pre” ]; then
After if [ “${1}” = “pre” ]; then
So, one “equal” sign less.
I’m running Linux Mint 19.1, kernel 4.18.0-13
I hope this is helpful for someone.
OK great. You might have a different shell to me, but anyway if it works, great.
When I run the example script, nothing happens.
I am running Ubuntu Mate 18.04.
Thanks.
Do you mean manually run it, or as part of suspend/resume? How do you know it’s not doing anything? The example script just writes to a file, do you have anything in that file?
It does not create a file when run manually or part of resume.
#!/bin/sh
#
# Created 3/31/19 in /usr/lib/systemd/system-sleep/
if [ “${1}” = “pre” ]; then
# Do the thing you want before suspend here
echo “we are suspending at $(date)…” > /home/andy/Downloads/systemd_suspend_test
elif [ “${1}” = “post” ]; then
# Do the thing you want after resume here
echo “…and we are back from $(date)” >> /home/andy/Downloads/systemd_suspend_test
/usr/bin/gxmessage -fg red -font ‘sans 30’ -timeout 3 ‘ Computer has now resumed from suspend state.’
fi
This was in my syslog.
Apr 1 10:14:33 7 systemd-sleep[32421]: System resumed.
Apr 1 10:14:33 7 systemd-sleep[32421]: /lib/systemd/system-sleep/On_Resume.sh: 2: [: post: unexpected operator
Apr 1 10:14:33 7 systemd-sleep[32421]: /lib/systemd/system-sleep/On_Resume.sh: 5: [: post: unexpected operator
I found out my problem. I forgot to set the execute bit.
My script works fine. 🙂
Hi Chris,
Thanks for the script! I almost… got it to work. I wanted to include a quick loop which would pause all my media applications before suspend (say closing laptop lid) so they wouldn’t start playing as soon as I open the lid (even before I log in).
So I tried this:
if [ "${1}" = "pre" ]; then
echo "start pre at $(date)..." > /tmp/systemd_suspend_test
for OUTPUT in $(playerctl -l)
do
playerctl -p $OUTPUT pause
done
echo $(playerctl -l) >> /tmp/systemd_suspend_test
elif [ "${1}" = "post" ]; then
echo "start post at $(date)..." >> /tmp/systemd_suspend_test
fi
The loop itself works perfectly when I execute it in the terminal manually. Unfortunately, it seems that the output of “playerctl -l” is empty as indicated by an empty line in the systemd_suspend_test file:
start pre at Thu 29 Oct 16:52:25 GMT 2020...
start post at Thu 29 Oct 16:52:30 GMT 2020...
Am I missing something? Any reason playerctl fails to run? I couldn’t find anything of use in the syslog file. I’m running Mint 20.
Best
Edvin
Hey Edvin, I expect this is probably something to do with this being run as `root` instead of your user.
You probably want to create a service like this instead:
https://wiki.archlinux.org/index.php/Power_management#Sleep_hooks
hi, i am trying to run a Python Script as followed:
#!/usr/bin/python3
import openrazer.client
devices = openrazer.client.DeviceManager().devices
for device in devices:
if device.name == “Razer Naga Trinity”:
device.fx.static(255,255,255)
this script works, it tells my mouse to set the leds to white.
i made it executable and copied it to /usr/bin/wakeup_trinity
next i copied an existing sycript in /usr/lib/systemd/system-sleep/ called hdparm to trinity and edited it like this:
#!/bin/sh
case $1 in
post)
python3 /usr/bin/wakeup_trinity
;;
esac
sadly it does not work. syslog tells me:
Nov 5 20:28:44 mimicri systemd-sleep[47560]: File “/usr/bin/wakeup_trinity”, line 4, in
Nov 5 20:28:44 mimicri [47545]: /usr/lib/systemd/system-sleep/trinity failed with exit status 1.
Please help, what is going wrong?
System is PopOS 20.10
thanks,
micha
If you execute that script exactly like the `systemd` service, does it work?
python3 /usr/bin/wakeup_trinity
Is it possible to display a GTK dialog before the suspend triggers?
I’m not sure, I haven’t tried that, sorry.. if you’re using X probably, not sure about Wayland. It also might not happen at the time you want it to. Would be something interesting to play with!
Hi @ll, is it possible to send ssh command before sudpend, and after?
With /usr/lib/system-sleep/ I ran into “Network is unreachable” error. (KDE 20.04)
THX for reply
Sorry, I haven’t tried that so I’m not sure. I expect it might be possible, but you’d need to modify some services to have a dependency on network.
Unable to remove the script i added to that location even after removing the file. The contents of the script still run after resuming from suspend
That’s interesting… can you post the output of
sudo ls -l /usr/lib/systemd/system-sleep/
by any chance? Also does it still happen after a reboot?Thanks man! Got my ThinkPad’s keyboard backlight fixed that way
#!/bin/sh
case $1 in
pre)
# save current keyboard backlight brightness
cat /sys/class/leds/tpacpi::kbd_backlight/brightness > /tmp/kbd_backlight_brightness
;;
post)
# restore saved value
cat /tmp/kbd_backlight_brightness > /sys/class/leds/tpacpi::kbd_backlight/brightness
;;
esac