Why is systemd not bringing down dependencies?

2

3

I have created a systemd service file, whose task is nothing, but just to bring up other services, and bring them down as well.

Since it does nothing, other than bringing up other services, i have put an echo to ExecStart and ExecStop.

The issue is, i can see the dependencies are brought up fine when i invoke service <myService> start, but they are not stopped when i call service <myService> stop. Even using BindsTo does not work.

Here is my service configuration file:

[Unit]
Description=Starts the DCCA index software
Requires=mysql.service ifmFuseHandler.service
After=mysql.service ifmFuseHandler.service
BindsTo=mysql.service ifmFuseHandler.service

[Install]
WantedBy=multi-user.target

[Service]
ExecStart=/bin/sh -c "echo 'Index started'"
ExecStop=/bin/sh -c "echo 'Index stopped'"

# Execute pre and post scripts as root
PermissionsStartOnly=true
Restart=on-failure

TimeoutSec=600
Type=forking
RemainAfterExit=yes

Solution: As suggested by @grawity i created a .target file called index-start.target as below:

[Unit]
Description=Starts the DCCA index software
Requires=mysql.service ifmFuseHandler.service
After=mysql.service ifmFuseHandler.service
BindsTo=mysql.service ifmFuseHandler.service

[Install]
WantedBy=multi-user.target

And a service file called index.service:

[Unit]
Description=Starts the DCCA index software
Requires=index-start.target
After=index-start.target

[Install]
WantedBy=multi-user.target index-start.target

[Service]
ExecStart=/bin/true
ExecStop=/bin/sh -c "echo 'Index stopped'"

# Execute pre and post scripts as root
PermissionsStartOnly=true
#Restart=on-failure (Commented as does not work with type=oneshot)

TimeoutSec=600
Type=oneshot
RemainAfterExit=yes

And when invoked, service index start it starts the dependencies and service index stop it stops the dependencies.

kingsmasher1

Posted 2016-01-12T10:03:19.873

Reputation: 299

Answers

4

First, you really should use a .target here, not a dummy service. (And for dummy services, Type=oneshot and ExecStart=/bin/true would be more fitting than forking.)

BindsTo= (and PartOf=) needs to be used in the opposite direction – it works just like Requires= in that this unit is stopped if the listed units disappear. So you need to add it to mysql.service and ifmFuseHandler.service instead. (Use drop-ins to extend the default mysql.service.)

user1686

Posted 2016-01-12T10:03:19.873

Reputation: 283 655

I just tried it once as-is using type=oneshot but it does not bring down the dependencies. I tried using ExecStop=/bin/false but looks like it does not exist, like /bin/true does. Pardon my ignorance, but is there a way out to stop it, using type=oneshot which you mentioned? Although, i wish to make it full-proof using the target later, but just for hands-on sake tried it. – kingsmasher1 – 2016-01-12T11:35:44.610

I tried using the .target but the issue is, there is no way to manually start or stop the service using the service xxxx start or service xxxx stop, which is also a required part, in addition to starting at boot time. Any way out? – kingsmasher1 – 2016-01-12T11:50:17.087

I created a .target file, as u indicated, and the same is edited and posted above. It works as expected, thanks. – kingsmasher1 – 2016-01-12T14:00:53.130

2

Thanks to your question/solution I got a good solution for me I'd like to share.
My requirement is to have a allservices.target which starts/stops/restarts srv1.service, srv2.service, and srv3.service.

A requirement is, that I could stop e.g. srv1.service and the other services and the target are still running after that.

The Key is to have the services in the Wants directive in the .target and in the srv*.services the PartOf=allservices.target

allservices.target

[Unit]
Description=start allservices
Wants=syslog.target network.target srv1.service srv2.service srv3.service 
After=network.target
[Install]
WantedBy=multi-user.target

srv1.service

[Unit]
Description=run srv1.service
Wants=syslog.target network.target
PartOf=allservices.target

[Service]
ExecStart=/path/to/bin/start
ExecStop=/bin/kill $MAINPID
Restart=always

[Install]
WantedBy=allservices.target

Like this after I hit systemctl start allservices.target srv1-srv3 are started, the same with stop and restart.
And if I run systemctl stop srv1.service the other services and the target are still running.

chloesoe

Posted 2016-01-12T10:03:19.873

Reputation: 627