[systemd-devel] systemd service start/stop conditions

Umut Tezduyar Lindskog umut at tezduyar.com
Wed Jul 9 00:11:04 PDT 2014


On Tue, Jul 8, 2014 at 1:00 PM, Mario Schuknecht
<mario.schuknecht at dresearch-fe.de> wrote:
> I have the following problem:
> There are 3 (or more) systemd targets. Each of the three targets starts a
> number of systemd services.
> It can be switched back and forth between the systemd targets.
>
> As a limitation, it is necessary that the services of a target start only if
> the services of actual target are already stopped. Because there have
> resources to be released, such as a serial port.
>
> The problem is solved with Unit paramter Conflicts. Starting a target will
> stop the other.

When you isolate a target, stop jobs are async. Your system could
complete isolation to a new target and still execute stop jobs from
previous target. At least this was the case around systemd 200 ish.
You might want to double check this with your "Conflicts" way if it is
same there. Otherwise, it will not be %100 bullet proof for you.

>
> The following systemd units demonstrate the problem.
> 3 systemd targets, 3 services and a dummy-program
> ================================
> mode-1.target
> --------------------
> [Unit]
> Description=mode 1
>
> Conflicts=mode-2.target
> Conflicts=mode-3.target
>
> [Install]
> WantedBy=multi-user.target
> ================================
> mode-2.target
> --------------------
> [Unit]
> Description=mode 2
>
> Conflicts=mode-1.target
> Conflicts=mode-3.target
>
> After=mode-1.target
>
> [Install]
> WantedBy=multi-user.target
> ================================
> mode-3.target
> --------------------
> [Unit]
> Description=mode 3
>
> Conflicts=mode-1.target
> Conflicts=mode-2.target
>
> After=mode-1.target
> After=mode-2.target
>
> [Install]
> WantedBy=multi-user.target
> ================================
> unit-a-resource-1.service
> -----------------------------------
> [Unit]
> Description=Unit A use resource 1
>
> After=mode-1.target
>
> Conflicts=mode-2.target
> Conflicts=mode-3.target
>
> [Service]
> ExecStart=/usr/bin/dummy_unit.sh "Unit A use resource 1"
> TimeoutSec=10
>
> [Install]
> WantedBy=mode-1.target
> ================================
> unit-b-resource-1.service
> -----------------------------------
> [Unit]
> Description=Unit B use resource 1
>
> After=mode-2.target
>
> Conflicts=mode-1.target
> Conflicts=mode-3.target
>
> [Service]
> ExecStart=/usr/bin/dummy_unit.sh "Unit B use resource 1"
>
>
> [Install]
> WantedBy=mode-2.target
> ================================
> unit-c-resource-2.service
> ------------------------------------
> [Unit]
> Description=Unit C use resource 2
>
> After=mode-3.target
>
> Conflicts=mode-1.target
> Conflicts=mode-2.target
>
> [Service]
> ExecStart=/usr/bin/dummy_unit.sh "Unit C use resource 2"
>
>
> [Install]
> WantedBy=mode-3.target
> ================================
> dummy_unit.sh
> ----------------------
> #!/bin/bash
>
> running=true
> trap 'echo got signal TERMinated; running=false' TERM
>
> echo "$1"
>
> # do something
> while $running
> do
>         sleep 1
> done
>
> # simulate longer shutdown
> sleep 1
> sleep 1
> sleep 1
> sleep 1
> sleep 1
>
> echo "$1 done"
> ================================
> #####################################
>
> Switch from mode-2.target to mode-1.target
> systemctl start mode-1.target
>
> systemd[1]: Stopping Unit B use resource 1...
> dummy_unit.sh[3303]: Terminated
> dummy_unit.sh[3303]: got signal TERMinated
> dummy_unit.sh[3303]: Terminated
> systemd[1]: Stopped Unit B use resource 1.
> dummy_unit.sh[3303]: Unit B use resource 1 done
> systemd[1]: Stopping mode 2.
> systemd[1]: Stopped target mode 2.
> systemd[1]: Starting mode 1.
> systemd[1]: Reached target mode 1.
> systemd[1]: Starting Unit A use resource 1...
> systemd[1]: Started Unit A use resource 1.
> dummy_unit.sh[3322]: Unit A use resource 1
>
> systemd service service unit-b-resource-1.service is stopped an than service
> unit-a-resource-1.service starts.
>
> This all works only if the line
>
> After=mode-1.target
>
> exist in mode-2.target and the lines
>
> After=mode-1.target
> After=mode-2.target
>
> exists in mode-3.target.
> =======================================
> Without these lines, it looks like this:
>
> Switch from mode-2.target to mode-1.target
> systemctl start mode-1.target
>
> systemd[1]: Stopping Unit B use resource 1...
> dummy_unit.sh[1009]: Terminated
> dummy_unit.sh[1009]: got signal TERMinated
> systemd[1]: Starting mode 1.
> systemd[1]: Reached target mode 1.
> systemd[1]: Starting Unit A use resource 1...
> dummy_unit.sh[1009]: Terminated
> systemd[1]: Started Unit A use resource 1.
> dummy_unit.sh[2873]: Unit A use resource 1
> dummy_unit.sh[1009]: Unit B use resource 1 done
> systemd[1]: Stopped Unit B use resource 1.
> systemd[1]: Stopping mode 2.
> systemd[1]: Stopped target mode 2.
>
> systemd service unit-a-resource-1.service starts before the other service
> unit-b-resource-1.service is stopped.
>
> Can anyone explain this behavior? (The parameter "After=" in mode-2.target
> and mode-3.target but not in mode-1.target)
> Can someone give a hint or a reference to the appropriate documentation?
> Or is this all working by change? I use systemd version 211.
> Is there a better solution?
>
> I hope I could describe the problem understandable.
>
> Regards,
>
> Mario
>
>
> _______________________________________________
> systemd-devel mailing list
> systemd-devel at lists.freedesktop.org
> http://lists.freedesktop.org/mailman/listinfo/systemd-devel
>


More information about the systemd-devel mailing list