4

I would like to have several systemd targets, call them TargetA, TargetB, and TargetC, that control a set of services, call them Service01 through Service7. The configuration would look something like this:

  • TargetA
    • Service1
    • Service2
    • Service3
  • TargetB wants
    • Service3
    • Service4
    • Service5
  • TargetC wants
    • Service5
    • Service6
    • Service7

Goals:

  • Only one target should be allowed to be enabled at a time
  • The system administrator should be able to manually start and services at will

My initial setup involved:

  • Each target conflicted with the other two targets
  • Every service had StopWhenUnneeded=true enabled

This met the first requirement. Starting TargetX stopped the other two targets. Unfortunately, this setup restricted the sysadmin. If the sysadmin ran sudo systemctl start ServiceX the service would launch and then immediately die because it wasn't needed.

My second setup involved:

  • Every target conflicted with the other two targets
  • Every target also conflicted with the services that it didn't need
  • No service has StopWhenUnneeded=true

For example:

  • TargetA
    • Wants
      • Service1
      • Service2
      • Service3
    • Conflicts
      • Service4
      • Service5
      • Service6
      • Service7
      • TargetB
      • TargetC

This doesn't have the desired effect. If I run:

sudo systemctl start TargetA.target

followed by:

sudo systemctl start TargetB.target

then TargetA.target is stopped (yay!) but Service1 and Service2 are still running.

What am I not getting? How can I get the systemd behavior that I'm looking for?

1 Answer 1

3

Suggested approach:

  1. Use systemctl isolate to start each of the 3 targets. As documented in man systemctl, this is a powerful command: "The isolate command will immediately stop processes that are not enabled in the new unit, possibly including the graphical environment or terminal you are currently using." Structure your target dependencies carefully! Possibly include multi-user.target as dependency.
  2. Make sure that that the first service the target starts is a special one that checks that the other targets are not active. This defends against an admin accidentally "starting" one of your custom targets instead of "isolating" it. You use /bin/systemctl is-active your.target to quickly check if it returns "active" or not.
2
  • I am attempting to avoid using systemctl isolate if I can. If I use systemctl isolate TargetA|B|C, then adding an unrelated TargetZ down the road because much more difficult, correct? Why does activating TargetB with sudo systemctl start TargetB.target not stop Service1 and Service2? Shouldn't Conflicts= directive stop them? Mar 20, 2017 at 14:02
  • It depends on how you want to use unrelated targets. You can create and start other targets, and they will run until you stop them or "isolate" a new target that doesn't depend on the unrelated targets. I'm not sure why Conflicts= isn't stopping the other services. man systemd.unit implies that it would. If you believe you've found a bug, you can file it at github.com/systemd/systemd/issues Mar 20, 2017 at 16:37

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.