23

I'd like to know if there's a way with Systemd to restart A.service (After) when B.service get started or reloaded (reload config only), if possible without editing B.service which is installed and upgraded by the system.

A.service should start even if B.service is not installed, disabled or stopped.

A.service:

[Unit]
After = B.service network-online.target
Wants = B.service

[Service]
Type=oneshot
ExecStart = /script.sh start
ExecStop = /script.sh stop
RemainAfterExit=yes

[Install]
WantedBy = network-online.target

B.service:

[Unit]
After=syslog.target network.target

[Service]
Type=forking
ExecStart=/cmd start
ExecStop=/cmd stop
ExecReload=/cmd reload
PIDFile=/var/run/cmd.pid

[Install]
WantedBy=multi-user.target

3 Answers 3

29
+50

You can use PartOf in the [Unit] section.

Example: PartOf=B.service

From man page,

PartOf=

Configures dependencies similar to Requires=, but limited to stopping and restarting of units. When systemd stops or restarts the units listed here, the action is propagated to this unit. Note that this is a one-way dependency — changes to this unit do not affect the listed units.

7
  • Thanks, I was looking into Overriding vendor settings but this looks even more easy and promising, only excpetion is I don't want A to stop if B stop, just A.restart if B.start, anyway I'll do some test soon and see if there's some way to manage it, then will let you know
    – Alex
    Nov 30, 2016 at 10:18
  • @Alex : What if you use PartOf and Restart=always together?
    – Thushi
    Dec 6, 2016 at 8:44
  • I'm looking at Restart= documentation, I'm not sure what is the behavior with oneshot services, but regardless: When the death of the process is a result of systemd operation (e.g. service stop or restart), the service will not be restarted, if I understand correctly manually stopping B would stop A
    – Alex
    Dec 6, 2016 at 10:38
  • 3
    Well now, the bounty auto-assigned itself for expiration, @Thushi I appreciate your effort and the suggestion but PartOf is not a solution for the question, enjoy anyway.
    – Alex
    Dec 6, 2016 at 20:58
  • @Alex: Well, Points are not important to me. There are so many other ways I can earn points. I just want to know whether the provided solution solves your issue. If not, we will work on it further. How about using PartOf with Restart=always? Did you tried that?
    – Thushi
    Dec 7, 2016 at 6:38
4

I had no control over stop with PartOf=, and A must not stop with B, so I ended up using Overriding vendor settings, seems to work.

/etc/systemd/system/B.service.d/override.conf

[Service]
ExecStart=
ExecStart=/bin/sh -c '/cmd start || exit $?; sleep 5; [ -x /script.sh ] && /script.sh start; exit 0'
ExecReload=
ExecReload=/bin/sh -c '/cmd reload || exit $?; sleep 5; [ -x /script.sh ] && /script.sh start; exit 0'

/cmd implementation is asynchronous and access a resource which /script.sh need to access too, I found nothing better (for now) to sleep few seconds.

I tried to use systemctl [--no-block] try-restart before using /script.sh directly but didn't work.

4
  • I am also looking for a solution for this scenario. Could you please explain this solution a bit more? or give a link to some docs to read and understand what you have done.
    – zappy
    Nov 1, 2018 at 4:41
  • Hi @zappy, look for the manual man systemd.unit (or search it online if isn't installed) and look for for the "Overriding vendor settings" chapter.
    – Alex
    Nov 1, 2018 at 15:29
  • Thank you for your input. I understand that you choose the above method only because service B is a vendor specific and you dont want to edit that service file. But in my case both service A and B are not vendor delivered. I feel overriding it may add complexity to the system. Do we have any other options ?
    – zappy
    Nov 5, 2018 at 6:13
  • The question is a couple of years old, did you check the documentation? Maybe this scenario has been covered since. At the time I was in a hurry but having time I would look for the systemd official mailing list and ask there, eventually open an issue
    – Alex
    Nov 5, 2018 at 10:08
3

At the moment systemd doesn't cover this senario. You can't achieve this functionality through service files alone. One possibility is to hijack systemctl via a shell script with the same name and in that check to see if B.service is about to be re/started or reloaded, do the appropriate action with A.service as well, and if needed update the rc.local to get to the proper state at boot as well. I have this problem with docker.service and networking.service, but I just always restart them together:

systemctl restart docker.service networking.service

Obviously, this would not be effective if systemd itself manipulate B.service internally ( e.g. via other service files.).

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .