If you create a Before= and an After= in your A.service file, you will get an error:
A.service: Job B.service/start deleted to break ordering cycle starting with A.service/start
Because Systemd doesn't want to have both of those dependencies on the same unit. I don't think that any of the Condition...= from man systemd.unit that Michael mentioned are well-suited for the task that you are trying to accomplish, unless your commands do create and then clean up their own files. The way I see it, you have two main possible solutions:
- Create an
ExecCondition= in your A.service that runs a command to check if B.service is running. This is a bit tricky to do with just ps and grep from within your unit file, so you'd probably want to execute some external script, but you already said you wanted to avoid a messy lockfile so that is probably not ideal.
- Use the messy lockfile solution that you mentioned that you didn't want to use
- Move your second command out of
B.service and into a ExecStopPost= option in A.service. This will cause the second command to run only after the first command has stopped. It will also prevent a new A.service from running before the first one completely finishes. I believe that this accomplishes all of your desires, since the A.service command and B.service command will never be run at the same time, two A.service commands will never be run alongside each other, and new executions will just be queued.
Here is the unit file that I used to test option 3:
[Unit]
Description = A.service for serverfault
[Service]
Type = oneshot
# A.service command
ExecStart = /usr/bin/sleep 3
# B.service command
ExecStopPost = /usr/bin/sleep 30
And then tested using systemctl start A.service repeatedly in multiple terminal windows, monitoring the progress of which processes were actually running at any given moment with ps.