How to start and stop a systemd unit with another?

20,614

I seem to have finally stumbled on the correct combination to get this working as desired.

In my firehose-announce.service unit I only set a BindsTo. The entire unit is:

[Unit]
Description=Firehose etcd announcer
BindsTo=firehose@%i.service

[Service]
EnvironmentFile=/etc/environment
TimeoutStartSec=30s
ExecStartPre=/bin/sh -c 'sleep 1'
ExecStart=/bin/sh -c "port=$(docker inspect -f '{{range $i, $e := .NetworkSettings.Ports }}{{$p := index $e 0}}{{$p.HostPort}}{{end}}' firehose-%i); echo -n \"Adding socket $COREOS_PRIVATE_IPV4:$port/tcp to /firehose/upstream/firehose-%i\"; while netstat -lnt | grep :$port >/dev/null; do etcdctl set /firehose/upstream/firehose-%i $COREOS_PRIVATE_IPV4:$port --ttl 300 >/dev/null; sleep 200; done"
RestartSec=30s
Restart=on-failure

[X-Fleet]
X-ConditionMachineOf=firehose@%i.service

This will cause the firehose-announce.service unit to stop when firehose.service does. Great. But how do we start it up again?

I reverse the dependency to be in my firehose.service unit like so:

[Unit]
Description=Firehose server
Wants=firehose-announce@%i.service
Before=firehose-announce@%i.service

[Service]
ExecStartPre=/usr/bin/docker pull firehose/server
ExecStartPre=-/usr/bin/docker rm -f firehose-%i
ExecStart=/usr/bin/docker run --name firehose-%i -p 7474 --env-file /home/core/firehose.env firehose/server
ExecStop=/usr/bin/docker rm -f firehose-%i
User=core
TimeoutStartSec=5m
TimeoutStopSec=20s
RestartSec=30s
Restart=on-failure

[Install]
WantedBy=multi-user.target

[X-Fleet]
X-Conflicts=firehose@*.service

This is saying that firehose.service wants firehose-announce.service to start up when it does (but don't fail if firehose-announce.service can't start). It also makes sure firehose.service starts before firehose-announce.service.

I tested this and the units now seem to stop and start together as desired.

Share:
20,614

Related videos on Youtube

Andy Shinn
Author by

Andy Shinn

Updated on September 18, 2022

Comments

  • Andy Shinn
    Andy Shinn over 1 year

    I am using CoreOS to schedule systemd units with fleet. I have two units (firehose.service and firehose-announce.service. I am trying to get the firehose-announce.service to start and stop along with the firehose.service. Here is the unit file for firehose-announce.service:

    [Unit]
    Description=Firehose etcd announcer
    BindsTo=firehose@%i.service
    After=firehose@%i.service
    Requires=firehose@%i.service
    
    [Service]
    EnvironmentFile=/etc/environment
    TimeoutStartSec=30s
    ExecStartPre=/bin/sh -c 'sleep 1'
    ExecStart=/bin/sh -c "port=$(docker inspect -f '{{range $i, $e := .NetworkSettings.Ports }}{{$p := index $e 0}}{{$p.HostPort}}{{end}}' firehose-%i); echo -n \"Adding socket $COREOS_PRIVATE_IPV4:$port/tcp to /firehose/upstream/firehose-%i\"; while netstat -lnt | grep :$port >/dev/null; do etcdctl set /firehose/upstream/firehose-%i $COREOS_PRIVATE_IPV4:$port --ttl 300 >/dev/null; sleep 200; done"
    RestartSec=30s
    Restart=on-failure
    
    [X-Fleet]
    X-ConditionMachineOf=firehose@%i.service
    

    I am trying to use BindsTo with the notion that start and stop of firehose.service will also start or stop firehose-announce.service. But this never happens correctly. If firehose.service is stopped, then firehose-announce.service goes to failed state. But when I start firehose.service, the firehose-announce.service doesn't start up.

    What am I doing wrong here?

    • nahime
      nahime over 9 years
      Same problem here. Have you found a solution?
  • nahime
    nahime over 9 years
    Great, I'll try it.
  • hookenz
    hookenz about 9 years
    Apparently, Wants= means optional. Requires= is a requirement. BindsTo means if dependancy i.e. firehose-service stops then firehose-announce service is considered stopped too. Sounds like a good thing to me.
  • buddy123
    buddy123 over 7 years
    Is it possible to get this behavior without touching firehouse.service?
  • Bug Killer
    Bug Killer over 7 years
    I tried this solution, but am running into one problem. I have service A with Requires=B.service and service B with BindsTo=A.service. When A exits abnormally, I see both A and B get restarted. But when A exits with code 0/SUCESS, both remain in stopped state
  • Northstrider
    Northstrider about 7 years
    ExecStartPre= {dash}'s - serve no purpose on the last one and only serve purpose on all but the last ExecStartPre
  • Cliff Armstrong
    Cliff Armstrong over 4 years
    @buddy123 use a "drop-in" override.