1

I need to run a script AFTER systemd has started the user dbus.service and run another script BEFORE systemd attempts to stop dbus.service. I don't want to modify the existing service files. The script is supposed to save and restore the loaded CDEmu images across reboots. The global service that called cdemu with --bus system has stopped working a few years ago, because in modern distros each user has their own set of loaded virtual images.

My current solution is having two user services: the -pre.service WantedBy=dbus.service and the -post.service that Requires=dbus.service

The latter is auto-stopped along with dbus.service. The first service must be enabled manually for each user who wants it. It starts the second service by launching systemctl start in background to avoid deadlock. Also, the first service stops immediately after start to properly handle dbus restart.

I want to know whether it's possible to reduce the number of services to just one, possibly with StopWhenUnneeded.

For testing I exit the X session and do:

$ systemctl --user stop dbus
$ systemctl --user start dbus

_

# /etc/systemd/user/dbus-pre.service
[Service]
ExecStart=/usr/local/bin/dbus-hook pre-start
# will be started again when dbus restarts
RemainAfterExit=false

[Install]
# systemctl --user enable dbus-pre
WantedBy=dbus.service

_

# /etc/systemd/user/dbus-post.service
[Service]
ExecStart=/usr/local/bin/dbus-hook post-start
ExecStop=/usr/local/bin/dbus-hook pre-stop
# oneshot supposed to spare dbus until ExecStop finishes
Type=oneshot
# RemainAfterExit=true prevents immediate stop of our service
RemainAfterExit=true

[Unit]
# Requires= supposed to stop us when dbus stops
Requires=dbus.service
# After= supposed to spare dbus until our service stops
After=dbus.service

_

#!/bin/bash
# /usr/local/bin/dbus-hook
echo "$1"
case $1 in
    pre-start)
        echo "starting dbus-post.service..."
        /usr/bin/systemctl --user start dbus-post.service >/dev/null 2>&1
        ;;
    post-start)
        echo "restoring cdemu mounts..."
        if [ -f ~/.config/cdemu.save ]; then
            {
                read -r x
                read -r x
                while read -r n b f; do
                    if [ x"True" = x"$b" ]; then
                        /usr/bin/cdemu load "$n" "$f"
                    fi
                done
            } <~/.config/cdemu.save
        fi
        ;;
    pre-stop)
        echo "saving cdemu mounts..."
        #echo "DBUS_SESSION_BUS_ADDRESS=$DBUS_SESSION_BUS_ADDRESS"
        if /usr/bin/pgrep -u "${USER:?}" -x cdemu-daemon >/dev/null; then
                mkdir -p ~/.config
            /usr/bin/cdemu status >~/.config/cdemu.save
        fi
        ;;
esac

Your Answer

By clicking "Post Your Answer", you acknowledge that you have read our updated terms of service, privacy policy and cookie policy, and that your continued use of the website is subject to these policies.

Browse other questions tagged or ask your own question.