Daemon - a small and powerful daemon supervisor, with (e)logind support, for babysitting our PipeWire's user target daemons - Testing Wanted
by ZhaoLin1457 from LinuxQuestions.org on (#5ETMD)
If you experimented with the PipeWire, either for bringing its services up for Wayland/Plasma5 or you wanted it as PulseAudio replacement, you know that it is a special kind of "daemon", basically just a program which has no idea to stop itself on user logout like PulseAudio, supposed to be managed by systemd as a "user target" service.
From the various experiments, looks like we have a proper way to start this PipeWire daemon, on early stage of desktop session's loading, using the XDG autostart.
However, until now, we haven't a consistent way to stop it on user logout, out of instructing elogind to kill user processes on logout. And this is not a desired behavior by many, as also are killed things like screen or tmux.
I believe that (ideally) we need a generic way to handle auto-quitting on user logout, considering that in future maybe we will want to handle more of those "user target" services designed for systemd based distributions.
A generic way like this is a daemon supervisor integrated with (e)logind which knows to quit its client program (and its own instance) on user logout, but there was no such thing.
So, I proposed this (e)logind integration (for auto-quitting) to the developer of "daemon", a small but features rich daemon supervisor which is capable to turn on well behaved daemons even bash scripts.
https://github.com/raforg/daemon/issues/1
The feature request was accepted and now its implementation is on advanced stage - soon will be made a stable release with it.
So, as more testing as we can is needed. Specially on Slackware, because it was requested and "designed" specially for it.
The usage is quite simple. To start the PipeWire instance supervised by this "daemon" you need only a XDG .desktop file put on /etc/xdg/autostart/pipewire.desktop with this content:
Code:Version=1.0
Name=PipeWire Media System
Comment=Start the PipeWire Media System
Exec=/usr/bin/daemon -fB /usr/bin/pipewire
Terminal=false
Type=Application
X-GNOME-Autostart-Phase=Initialization
X-KDE-autostart-phase=1On the graphical session startup the "daemon" will be executed with instructions to run "pipewire" and to watch user sessions for logout. And to stay on foreground, BTW...
No more customization is needed, as the "daemon" will known to quit itself and its client on user logout.
As I tested myself, this works fine, both as root and unprivileged user, but will be very useful if there's more testing. With the note that the developer himself uses Debian and tests it against systemd, so we are only who can test this feature exactly for what we need it.
To build this "daemon" we need to grab the code from its "main" branch from GitHub, and bellow the scripts which I use.
fetch-daemon.sh was borrowed and adapted from Mr. Volkerding's fetch-efibootmgr.sh
Code:#!/bin/sh
# Copyright 2019 Patrick J. Volkerding, Sebeka, Minnesota, USA
# All rights reserved.
#
# Redistribution and use of this script, with or without modification, is
# permitted provided that the following conditions are met:
#
# 1. Redistributions of this script must retain the above copyright
# notice, this list of conditions and the following disclaimer.
#
# THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
# WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
# MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
# EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
# PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
# OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
# WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
# OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
# ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
# Pull a stable branch + patches
BRANCH=${1:-main}
# Clear download area:
rm -rf daemon
# Clone repository:
git clone https://github.com/raforg/daemon.git
# checkout $BRANCH:
( cd daemon
git checkout $BRANCH || exit 1
)
HEADISAT="$( cd daemon && git log -1 --format=%h )"
DATE="$( cd daemon && git log -1 --format=%cd --date=format:%Y%m%d )"
LONGDATE="$( cd daemon && git log -1 --format=%cd --date=format:%c )"
# Cleanup. We're not packing up the whole git repo.
( cd daemon && find . -type d -name ".git*" -exec rm -rf {} \; 2> /dev/null )
mv daemon daemon-${DATE}_${HEADISAT}
tar cf daemon-${DATE}_${HEADISAT}.tar daemon-${DATE}_${HEADISAT}
xz -9 -f daemon-${DATE}_${HEADISAT}.tar
rm -rf daemon-${DATE}_${HEADISAT}
touch -d "$LONGDATE" daemon-${DATE}_${HEADISAT}.tar.xz
echo
echo "daemon branch $BRANCH with HEAD at $HEADISAT packaged as daemon-${DATE}_${HEADISAT}.tar.xz"
echodaemon.SlackBuild was also adapted from one of Mr. Volkerding's build scripts.
Code:#!/bin/bash
# Copyright 2005-2018 Patrick J. Volkerding, Sebeka, MN, USA
# All rights reserved.
#
# Redistribution and use of this script, with or without modification, is
# permitted provided that the following conditions are met:
#
# 1. Redistributions of this script must retain the above copyright
# notice, this list of conditions and the following disclaimer.
#
# THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
# WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
# MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
# EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
# PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
# OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
# WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
# OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
# ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
cd $(dirname $0) ; CWD=$(pwd)
PKGNAM=daemon
VERSION=${VERSION:-$(echo $PKGNAM-*.tar.?z | rev | cut -f 3- -d . | cut -f 1 -d - | rev)}
BUILD=${BUILD:-1}
NUMJOBS=${NUMJOBS:-" -j$(expr $(nproc) + 1) "}
# Automatically determine the architecture we're building on:
if [ -z "$ARCH" ]; then
case "$( uname -m )" in
i?86) export ARCH=i586 ;;
arm*) export ARCH=arm ;;
# Unless $ARCH is already set, use uname -m for all other archs:
*) export ARCH=$( uname -m ) ;;
esac
fi
# If the variable PRINT_PACKAGE_NAME is set, then this script will report what
# the name of the created package would be, and then exit. This information
# could be useful to other scripts.
if [ ! -z "${PRINT_PACKAGE_NAME}" ]; then
echo "$PKGNAM-$VERSION-$ARCH-$BUILD.txz"
exit 0
fi
TMP=${TMP:-/tmp}
PKG=$TMP/package-$PKGNAM
rm -rf $PKG
mkdir -p $TMP $PKG
cd $TMP
rm -rf $PKGNAM-$VERSION
tar xvf $CWD/$PKGNAM-$VERSION.tar.?z || exit 1
cd $PKGNAM-$VERSION || exit 1
chown -R root:root .
find . \
\( -perm 777 -o -perm 775 -o -perm 711 -o -perm 555 -o -perm 511 \) \
-exec chmod 755 {} \+ -o \
\( -perm 666 -o -perm 664 -o -perm 600 -o -perm 444 -o -perm 440 -o -perm 400 \) \
-exec chmod 644 {} \+
./configure --prefix=/usr
make $NUMJOBS || make || exit 1
make html || exit 1
make install DESTDIR=$PKG
make install-daemon-conf DESTDIR=$PKG
mkdir -p $PKG/usr/doc/$PKGNAM-$VERSION
cp -a \
COPYING* INSTALL LICENSE README* REFERENCES daemon.1.html \
$PKG/usr/doc/$PKGNAM-$VERSION
# If there's a CHANGELOG, installing at least part of the recent history
# is useful, but don't let it get totally out of control:
if [ -r CHANGELOG ]; then
DOCSDIR=$(echo $PKG/usr/doc/*-$VERSION)
cat CHANGELOG | head -n 1000 > $DOCSDIR/CHANGELOG
touch -r CHANGELOG $DOCSDIR/CHANGELOG
fi
mkdir -p $PKG/install
cat $CWD/slack-desc > $PKG/install/slack-desc
# Build the package:
cd $PKG
/sbin/makepkg -l y -c n $TMP/$PKGNAM-$VERSION-$ARCH-$BUILD.txzAnd the associated slack-desc
Code:# HOW TO EDIT THIS FILE:
# The "handy ruler" below makes it easier to edit a package description. Line
# up the first '|' above the ':' following the base package name, and the '|'
# on the right side marks the last column you can put a character in. You must
# make exactly 11 lines for the formatting to be correct. It's also
# customary to leave one space after the ':'.
|-----handy-ruler------------------------------------------------------|
daemon: daemon (turns other processes into daemons)
daemon:
daemon: Daemon turns other processes into daemons. There are many tasks that
daemon: need to be performed to correctly set up a daemon process. This can
daemon: be tedious. Daemon performs these tasks for other processes. This is
daemon: useful for writing daemons in languages other than C, C++ or Perl
daemon: (e.g. `/bin/sh`, Java).
daemon:
daemon: http://libslack.org/daemon/
daemon:
daemon:Like I said, from my own tests, looks like the "daemon" handles well the PipeWire service, and there could be further customization like ensuring that the PipeWire daemon runs and eventually restarting it on crash or that a unique instance of PipeWire is started per user.
But, I believe that the really nice thing of this design is that the usage of this "daemon" is not limited to PipeWire babysitting, but could be used for any other "user target" daemons designed to be run by systemd.
However, the usefulness of this daemon supervisor is way over its (right now unique) feature of (e)logind integration, as it can be used by various services, and for turning on well behaved daemons various applications and even scripts.
For example, the Laravel Framework, a well known MVC Framework made on PHP, needs to run a background program (of course written on PHP) to execute various off-line tasks. This "daemon" is a nice solution for having even a background service written on PHP too.


From the various experiments, looks like we have a proper way to start this PipeWire daemon, on early stage of desktop session's loading, using the XDG autostart.
However, until now, we haven't a consistent way to stop it on user logout, out of instructing elogind to kill user processes on logout. And this is not a desired behavior by many, as also are killed things like screen or tmux.
I believe that (ideally) we need a generic way to handle auto-quitting on user logout, considering that in future maybe we will want to handle more of those "user target" services designed for systemd based distributions.
A generic way like this is a daemon supervisor integrated with (e)logind which knows to quit its client program (and its own instance) on user logout, but there was no such thing.
So, I proposed this (e)logind integration (for auto-quitting) to the developer of "daemon", a small but features rich daemon supervisor which is capable to turn on well behaved daemons even bash scripts.
https://github.com/raforg/daemon/issues/1
The feature request was accepted and now its implementation is on advanced stage - soon will be made a stable release with it.
So, as more testing as we can is needed. Specially on Slackware, because it was requested and "designed" specially for it.
The usage is quite simple. To start the PipeWire instance supervised by this "daemon" you need only a XDG .desktop file put on /etc/xdg/autostart/pipewire.desktop with this content:
Code:Version=1.0
Name=PipeWire Media System
Comment=Start the PipeWire Media System
Exec=/usr/bin/daemon -fB /usr/bin/pipewire
Terminal=false
Type=Application
X-GNOME-Autostart-Phase=Initialization
X-KDE-autostart-phase=1On the graphical session startup the "daemon" will be executed with instructions to run "pipewire" and to watch user sessions for logout. And to stay on foreground, BTW...
No more customization is needed, as the "daemon" will known to quit itself and its client on user logout.
As I tested myself, this works fine, both as root and unprivileged user, but will be very useful if there's more testing. With the note that the developer himself uses Debian and tests it against systemd, so we are only who can test this feature exactly for what we need it.
To build this "daemon" we need to grab the code from its "main" branch from GitHub, and bellow the scripts which I use.
fetch-daemon.sh was borrowed and adapted from Mr. Volkerding's fetch-efibootmgr.sh
Code:#!/bin/sh
# Copyright 2019 Patrick J. Volkerding, Sebeka, Minnesota, USA
# All rights reserved.
#
# Redistribution and use of this script, with or without modification, is
# permitted provided that the following conditions are met:
#
# 1. Redistributions of this script must retain the above copyright
# notice, this list of conditions and the following disclaimer.
#
# THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
# WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
# MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
# EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
# PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
# OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
# WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
# OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
# ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
# Pull a stable branch + patches
BRANCH=${1:-main}
# Clear download area:
rm -rf daemon
# Clone repository:
git clone https://github.com/raforg/daemon.git
# checkout $BRANCH:
( cd daemon
git checkout $BRANCH || exit 1
)
HEADISAT="$( cd daemon && git log -1 --format=%h )"
DATE="$( cd daemon && git log -1 --format=%cd --date=format:%Y%m%d )"
LONGDATE="$( cd daemon && git log -1 --format=%cd --date=format:%c )"
# Cleanup. We're not packing up the whole git repo.
( cd daemon && find . -type d -name ".git*" -exec rm -rf {} \; 2> /dev/null )
mv daemon daemon-${DATE}_${HEADISAT}
tar cf daemon-${DATE}_${HEADISAT}.tar daemon-${DATE}_${HEADISAT}
xz -9 -f daemon-${DATE}_${HEADISAT}.tar
rm -rf daemon-${DATE}_${HEADISAT}
touch -d "$LONGDATE" daemon-${DATE}_${HEADISAT}.tar.xz
echo
echo "daemon branch $BRANCH with HEAD at $HEADISAT packaged as daemon-${DATE}_${HEADISAT}.tar.xz"
echodaemon.SlackBuild was also adapted from one of Mr. Volkerding's build scripts.
Code:#!/bin/bash
# Copyright 2005-2018 Patrick J. Volkerding, Sebeka, MN, USA
# All rights reserved.
#
# Redistribution and use of this script, with or without modification, is
# permitted provided that the following conditions are met:
#
# 1. Redistributions of this script must retain the above copyright
# notice, this list of conditions and the following disclaimer.
#
# THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
# WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
# MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
# EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
# PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
# OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
# WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
# OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
# ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
cd $(dirname $0) ; CWD=$(pwd)
PKGNAM=daemon
VERSION=${VERSION:-$(echo $PKGNAM-*.tar.?z | rev | cut -f 3- -d . | cut -f 1 -d - | rev)}
BUILD=${BUILD:-1}
NUMJOBS=${NUMJOBS:-" -j$(expr $(nproc) + 1) "}
# Automatically determine the architecture we're building on:
if [ -z "$ARCH" ]; then
case "$( uname -m )" in
i?86) export ARCH=i586 ;;
arm*) export ARCH=arm ;;
# Unless $ARCH is already set, use uname -m for all other archs:
*) export ARCH=$( uname -m ) ;;
esac
fi
# If the variable PRINT_PACKAGE_NAME is set, then this script will report what
# the name of the created package would be, and then exit. This information
# could be useful to other scripts.
if [ ! -z "${PRINT_PACKAGE_NAME}" ]; then
echo "$PKGNAM-$VERSION-$ARCH-$BUILD.txz"
exit 0
fi
TMP=${TMP:-/tmp}
PKG=$TMP/package-$PKGNAM
rm -rf $PKG
mkdir -p $TMP $PKG
cd $TMP
rm -rf $PKGNAM-$VERSION
tar xvf $CWD/$PKGNAM-$VERSION.tar.?z || exit 1
cd $PKGNAM-$VERSION || exit 1
chown -R root:root .
find . \
\( -perm 777 -o -perm 775 -o -perm 711 -o -perm 555 -o -perm 511 \) \
-exec chmod 755 {} \+ -o \
\( -perm 666 -o -perm 664 -o -perm 600 -o -perm 444 -o -perm 440 -o -perm 400 \) \
-exec chmod 644 {} \+
./configure --prefix=/usr
make $NUMJOBS || make || exit 1
make html || exit 1
make install DESTDIR=$PKG
make install-daemon-conf DESTDIR=$PKG
mkdir -p $PKG/usr/doc/$PKGNAM-$VERSION
cp -a \
COPYING* INSTALL LICENSE README* REFERENCES daemon.1.html \
$PKG/usr/doc/$PKGNAM-$VERSION
# If there's a CHANGELOG, installing at least part of the recent history
# is useful, but don't let it get totally out of control:
if [ -r CHANGELOG ]; then
DOCSDIR=$(echo $PKG/usr/doc/*-$VERSION)
cat CHANGELOG | head -n 1000 > $DOCSDIR/CHANGELOG
touch -r CHANGELOG $DOCSDIR/CHANGELOG
fi
mkdir -p $PKG/install
cat $CWD/slack-desc > $PKG/install/slack-desc
# Build the package:
cd $PKG
/sbin/makepkg -l y -c n $TMP/$PKGNAM-$VERSION-$ARCH-$BUILD.txzAnd the associated slack-desc
Code:# HOW TO EDIT THIS FILE:
# The "handy ruler" below makes it easier to edit a package description. Line
# up the first '|' above the ':' following the base package name, and the '|'
# on the right side marks the last column you can put a character in. You must
# make exactly 11 lines for the formatting to be correct. It's also
# customary to leave one space after the ':'.
|-----handy-ruler------------------------------------------------------|
daemon: daemon (turns other processes into daemons)
daemon:
daemon: Daemon turns other processes into daemons. There are many tasks that
daemon: need to be performed to correctly set up a daemon process. This can
daemon: be tedious. Daemon performs these tasks for other processes. This is
daemon: useful for writing daemons in languages other than C, C++ or Perl
daemon: (e.g. `/bin/sh`, Java).
daemon:
daemon: http://libslack.org/daemon/
daemon:
daemon:Like I said, from my own tests, looks like the "daemon" handles well the PipeWire service, and there could be further customization like ensuring that the PipeWire daemon runs and eventually restarting it on crash or that a unique instance of PipeWire is started per user.
But, I believe that the really nice thing of this design is that the usage of this "daemon" is not limited to PipeWire babysitting, but could be used for any other "user target" daemons designed to be run by systemd.
However, the usefulness of this daemon supervisor is way over its (right now unique) feature of (e)logind integration, as it can be used by various services, and for turning on well behaved daemons various applications and even scripts.
For example, the Laravel Framework, a well known MVC Framework made on PHP, needs to run a background program (of course written on PHP) to execute various off-line tasks. This "daemon" is a nice solution for having even a background service written on PHP too.