I had the same problem - after calling command wrapped by systemd-inhibit
my laptop successfully went to a sleep state.
I haven't found a solution to this issue, but i have a good workaround. (I'm using archlinux, yet, i believe it should work in most cases.)
The main idea is to wrap the main service (binary or script) that is implementing sleeping functionality.
1. Find the main service
$ systemctl status systemd-suspend.service
○ systemd-suspend.service - System Suspend
Loaded: loaded (/usr/lib/systemd/system/systemd-suspend.service; static)
Check contents of /usr/lib/systemd/system/systemd-suspend.service
$ cat /usr/lib/systemd/system/systemd-suspend.service
...
[Service]
Type=oneshot
ExecStart=/usr/lib/systemd/systemd-sleep suspend
And the winner is /usr/lib/systemd/systemd-sleep.
Note that it consumes one argument, so wrapper script shouldn't lose it. As a bonus, we will fix all other modes (poweroff and hibernate) in a one place.
$ file /usr/lib/systemd/systemd-sleep
/usr/lib/systemd/systemd-sleep: ELF 64-bit LSB pie executable, x86-64, version 1 (SYSV), dynamically linked, interpreter /lib64/ld-linux-x86-64.so.2, BuildID[sha1]=fa6da37bf95f4a7255909a8e18fecbc1f3910acc, for GNU/Linux 4.4.0, stripped
2. Move it
sudo mv /usr/lib/systemd/systemd-sleep /usr/lib/systemd/systemd-sleep.bin
3. Create a wrapper script
For example, in my .bash_aliases i have:
alias lxcexport="systemd-inhibit lxc image export"
. Export called by this alias should block sleep service until lxc finishes container export.
In systemd-inhibit
report it's marked blocked by a systemd-inhibit COMMand:
$ systemd-inhibit --list --no-pager
WHO UID USER PID COMM WHAT WHY MODE
...
lxc image export server:container… 1000 cot 868971 systemd-inhibit shutdown:sleep:idle Unknown… block
...
So in wrapper script we delay called sleep action for a predefined delay (e.g. 5 sec) while systemd-inhibit --list --no-pager --no-legend|grep systemd-inhibit
returns non-empty result. After lock is released, grep will return nothing and the script will continue and call the main sleep service binary with passed argument.
NB Keep in mind once it fires, it won't automatically stop on user re-activation. i.e. it will continue action ignoring you.
sudo vi /usr/lib/systemd/systemd-sleep.wrapper
#!/bin/sh
while test -n "$(systemd-inhibit --list --no-pager --no-legend|grep systemd-inhibit)" ; do
printf '.'
sleep 5
done
/usr/lib/systemd/systemd-sleep.bin $1
Make it executable.
sudo chmod +x /usr/lib/systemd/systemd-sleep
Finally, create a link to the wrapper script. That way, you won't lose the wrapper script if a planned system update overwrites systemd-sleep.
sudo ln -s /usr/lib/systemd/systemd-sleep.wrapper /usr/lib/systemd/systemd-sleep
In log it looks smth like that:
May 09 08:54:53 LIVE.ARCH.BOX systemd-logind[798]: The system will suspend now!
May 09 08:54:53 LIVE.ARCH.BOX systemd[1]: Reached target Sleep.
May 09 08:54:53 LIVE.ARCH.BOX systemd[1]: Starting System Suspend...
May 09 08:54:53 LIVE.ARCH.BOX systemd-logind[798]: Operation 'sleep' finished.
May 09 08:58:27 LIVE.ARCH.BOX systemd[1545]: snap.lxd.lxc.9a9d4293-449f-4314-91b3-02aca1c4006b.scope: Consumed 4min 39.349s CPU time.
May 09 08:58:29 LIVE.ARCH.BOX systemd-sleep[859442]: ...........................................
May 09 08:58:29 LIVE.ARCH.BOX systemd-sleep[863081]: Going to suspend...
May 09 08:58:29 LIVE.ARCH.BOX systemd-sleep[863080]: Going to suspend...
May 09 08:58:29 LIVE.ARCH.BOX systemd-sleep.bin[863078]: Entering sleep state 'suspend'...
May 09 08:58:29 LIVE.ARCH.BOX kernel: PM: suspend entry (deep)
May 09 08:58:29 LIVE.ARCH.BOX kernel: Filesystems sync: 0.487 seconds
TIP
The same can be done with pm-utils (but this time i've modified action script directly) :
$ which pm-hibernate
/usr/bin/pm-hibernate
10:24:34 [cot@LIVE ~]$ ls -la /usr/bin/pm-hibernate
lrwxrwxrwx 1 root root 31 May 8 2021 /usr/bin/pm-hibernate -> /usr/lib/pm-utils/bin/pm-action
.
$ cat /usr/lib/pm-utils/bin/pm-action
...
command_exists "check_$METHOD" && command_exists "do_$METHOD" || {
log "pm-utils does not know how to $METHOD on this system."
exit 1
}
##delay if systemd-inhibit was called by someone
while test -n "$(systemd-inhibit --list --no-pager --no-legend|grep systemd-inhibit)" ; do
printf '.'
sleep 55
done
...