systemd: How to wait for a device before starting a service

Richard Shaw hobbes1069 at gmail.com
Fri Jan 6 20:55:35 UTC 2012


Ok, I didn't know how to make the subject any shorter, but there's a
big BUT in this, but (hehe) first a summary.

I have a user of MythTV that has capture devices which require a
firmware be uploaded. As a consequence, the /dev paths are not always
created by the time mythbackend tries to start. A solution to this is
to create a mythbackend.path unit file which will wait for the devices
to be created, BUT, they occasionally fail to initialize and the path
unit file doesn't seem to have a timeout option (or option for what to
do once the timeout is reached).

A partial solution would be to use a timer unit file, but it too
doesn't do quite what I need. It doesn't appear that I can wait for
the start of one unit file (mythbackend.path) while starting a
different unit file (mythbackend.service) once the timeout is reached.

I could use the same 'After=...' as I have on the main service file
which would approximate the same startup time, but that's rather
hackish. I am assuming that having two unit files (a path and a timer)
trying to start the same service isn't an issue and that the first one
wins.

Below is the entire message I was sent with his solution which is even
more complicated than what I'm proposing, but appears to work.

Thanks,
Richard


---------- Forwarded message ----------
From: Gary
Date: Fri, Jan 6, 2012 at 1:41 PM
Subject: mythbackend.service file questions/suggestions.
To: hobbes1069 at gmail.com


Hi,

As the maintainer of the rpmfusion mythtv package,
I thought I would provide some feedback on the
systemd scripts currently being shipped.

I have found that in Fedora 16 to get mythtv backend to
(more or less) reliably startup after a system reboot, I
have had to modify the service files as shown below.
The reason is that for some capture devices, there
is additional processing (i.e. firmware downloads)
that can take an extended time to complete
(in my case, 6 tuners using the pvrusp2 driver, which
take around 70 seconds after boot on a slow system).

The intent is to wait for the capture device paths
to exist, and only when all are there, start the
backend.  As a fallback, start the backend no
matter what after 2 minutes (in the case where
one or more capture cards never initialize).

I am not entirely sure that this is the correct
way to do this, but various other methods I
tried did not seem to work.  If you, or someone
you know, know systemd better, please share,
and feel free to use any of this as appropriate.


Thanks for the work packaging mythtv for rpmfusion!

Gary




---New File:  mythbackend-waitdev.path

[Unit]
Description=MythTV backend service startup delay until capture devices exist

[Path]

#
# "Dummy" (always existing) file to keep systemd happy
# (if there is no items in the [Path], systemd complains)
#
PathExists=/dev/null

#
# List all devices the mythbackend would try to initialize.
# For each (new) device, this unit will try to start the
# related service, which will start only when all devices
# are ready.  These should normally be the udev persistent
# rule names to avoid confusion.
#
# You must also update the service file with the same
# capture device paths.
#

# PathExists=/dev/video300
# PathExists=/dev/video301

[Install]
WantedBy=multi-user.target


---New File:  mythbackend-waitdev.service

[Unit]
Description=MythTV backend service startup delay until capture devices exist

#
# Create an entry for all the capture devices that
# one wishes to wait to be created.  These normally
# should be udev persistent rule names to avoid
# confusion.
#
# You must also update the path unit with the same
# device names
#

# ConditionPathExists=/dev/video300
# ConditionPathExists=/dev/video301

[Service]
Type=oneshot
ExecStart=/bin/systemctl start mythbackend.service
RemainAfterExit=true


---New File:  mythbackend.timer

#
# Normally the MythTV backend will be started
# after all capture devices have been initialized,
# but if one (or more) does not, we still want
# to start the backend.  This timer will do that.
#

[Unit]
Description=MythTV backend service startup after delay (failsafe startup)

[Timer]
OnActiveSec=120

[Install]
WantedBy=multi-user.target


---Modified file: mythbackend.service (removed [Install])

[Unit]
Description=MythTV backend service
After=network.target mysqld.service

[Service]
Type=simple
Environment=MYTHCONFDIR=/etc/mythtv
Environment=HOME=/usr/share/mythtv
User=mythtv
ExecStart=/usr/bin/mythbackend --logfile /var/log/mythtv/mythbackend.log


More information about the devel mailing list