3

I'm trying to create dependencies between two services described in systemd unit files:

  • a.service has to start before b.service
  • b.service can not start if a.service fails

Here is what I have:

% cat a.service
[Unit]
Description=A-Service
Before=b.service

[Service]
ExecStart=/opt/a.sh

[Install]
WantedBy=multi-user.target

% cat b.service
[Unit]
Description=B-Service
After=a.service

[Service]
ExecStart=/opt/b.sh

[Install]
WantedBy=multi-user.target

And this are simple scripts executed for service A and B:

% cat a.sh
#!/bin/sh
echo "A service started"
exit 0

% cat b.sh
#!/bin/sh
echo "B service started"
while [ true ]; do
   sleep 1
do
exit 0

So I've tried to emulate a/service failure by returning exit 1 from a.sh, systemctl status a.service reports it as failed:

Active: failed (Result: exit-code) ...
Process: 843 ExecStart=/opt/a.sh (code=exited, status=1/FAILURE)
...

However b.service still starts and active:

% systemctl status b.service
...
Active: active (running) ...
Process: 844 ExecStart=/opt/b.sh (code=exited, status=0/SUCCESS)
...

Moreover b.service dependencies do contain a.service (with status Fail):

% systemctl list-dependencies b.service
...

What am I doing wrong? Is it a problem with the scripts or [Unit] definition is not complete?

1 Answer 1

4

I would use a Requires attribute in the second unit:

If this unit gets activated, the units listed will be activated as well. If one of the other units fails to activate, and an ordering dependency After= on the failing unit is set, this unit will not be started.

I also changed the Type of each unit to be forking, since the default type of "simple" will consider the unit started once the shell has been started, while a forking unit will wait for the shell to exit. This Type change is critical here only for A-Service.

I also removed Before=b.service from A-Service, since a backwards dependency from B -to- A (with B's "After" directive) makes more sense to me, and you don't have to have both.

The resulting unit files are:

[Unit]
Description=A-Service

[Service]
Type=forking
ExecStart=/opt/a.sh

[Install]
WantedBy=multi-user.target

and:

[Unit]
Description=B-Service
Requires=a.service
After=a.service

[Service]
Type=forking
ExecStart=/opt/b.sh

[Install]
WantedBy=multi-user.target

You must log in to answer this question.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.