Running scripts before and after suspend with systemd

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

16 thoughts on “Running scripts before and after suspend with systemd

  1. Pingback: Links 11/5/2016: Docker Security, Cinnamon 3.0.2 | Techrights

  2. Sampi

    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.

  3. Supersonic Tumbleweed

    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!

  4. Hannah

    Thanks, now my keyboard backlight settings get saved and restored correctly on suspend/resume 🙂

  5. Chris Post author

    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

  6. Klaus

    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).

  7. Tero

    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.

  8. andrew kennedy

    When I run the example script, nothing happens.

    I am running Ubuntu Mate 18.04.

    Thanks.

  9. Chris Post author

    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?

    cat /tmp/systemd_suspend_test
  10. andrew kennedy

    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

  11. andrew kennedy

    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

  12. andrew kennedy

    I found out my problem. I forgot to set the execute bit.

    My script works fine. 🙂

Leave a Reply

Your email address will not be published. Required fields are marked *