Systemctl dependency failure, stop dependent services - linux

I have 2 services a.service and b.service.
a.service is shown
[Unit]
Description=My service
[Service]
Type=forking
ExecStart=/bin/sh /home/admin/run.sh
Restart=on-failure
[Install]
WantedBy=multi-user.target,
b.service
[Unit]
Description=My service
[Service]
Type=forking
ExecStart=/bin/sh $HOME/theFolder/run.sh
Restart=on-failure
[Install]
WantedBy=multi-user.target
Now, when i start b.service, i'm sure a.service will be started.
During runtime, suddenly someone messes with /home/admin/run.sh and systemd is unable to start a.service (also systemctl status a.service shows failed as status). Now is there a option so that b.service can know that a.service is failed and it should stop/exit?

You want to add either BindsTo= or Requires= to your [Unit] section, as documented in man systemd.unit:
Requires=
Configures requirement dependencies on other units. If this unit gets activated, the units listed here
will be activated as well. If one of the other units gets deactivated or its activation fails, this unit
will be deactivated. This option may be specified more than once or multiple space-separated units may
be specified in one option in which case requirement dependencies for all listed names will be created.
Note that requirement dependencies do not influence the order in which services are started or stopped.
This has to be configured independently with the After= or Before= options. If a unit foo.service
requires a unit bar.service as configured with Requires= and no ordering is configured with After= or
Before=, then both units will be started simultaneously and without any delay between them if
foo.service is activated. Often, it is a better choice to use Wants= instead of Requires= in order to
achieve a system that is more robust when dealing with failing services.
BindsTo=
Configures requirement dependencies, very similar in style to Requires=, however in addition to this
behavior, it also declares that this unit is stopped when any of the units listed suddenly disappears.
Units can suddenly, unexpectedly disappear if a service terminates on its own choice, a device is
unplugged or a mount point unmounted without involvement of systemd.

Related

Can't manage to start a task when bluetooth is ready with systemd

I'm trying to start a task when bluetooth is ready on a raspi (running raspbian 10 - buster) with systemd.
I've added the file /lib/systemd/system/my.service with this content
[Unit]
After=bluetooth.target
[Service]
Type=idle
ExecStart=/root/my.sh
[Install]
Wants=bluetooth.target
When I look at what happens on startup with the graph created by systemd-analyse plot, I see that my service is started way before the bluetooth.target unit is activated.
But when I check with systemctl show my.service, it says
...
After=basic.target bluetooth.target system.slice systemd-journald.socket sysinit.target
...
So can someone explains me why my service doesn't start after bluetooth.target?
Thanx
[edit]
I've followed advice from #ukBaz and moved my service file to /etc/systemd/system and moved the Wants stanza to the Unit section (actually I changed it to 'Requires').
So my file now contains
[Unit]
After=bluetooth.target
Requires=bluetooth.target
[Service]
Type=idle
ExecStart=/root/my.sh
[Install]
WantedBy=multi-user.target
Now my service starts after bluetooth.target... but bluetooth.target gets started very early!
And systemctl show bluetooth.target tells me 'After=bluetooth.service' so how come it is started/reached way before bluetooth.service?
The system’s copy of unit files are generally kept in the /lib/systemd/system directory. When software installs unit files on the system, this is the location where they are placed by default.
If you wish to modify the way that a unit functions or create your own, the best location to do so is within the /etc/systemd/system directory. Unit files found in this directory location take precedence over any of the other locations on the filesystem.
Wants should be in the [Unit] section not in the [Install] section.
[Install] section is optional and is used to define the behaviour of a unit if it is enabled or disabled. I have only every put WantedBy=multi-user.target in this section. The multi-user.target tells systemd (as I understand it) that it is needed for “normal operation”.

How to restart bluetooth service when my server service restarts in systemd

I am using systemd services on an embedded system. I have a web service that needs to restart bluetooth everytime it restarts. How do I write the unit file for this. Also the service I have is put into systemd/user and not systemd/system.
I tried using PartOf=bluetooth.service but that didn't work.
[Unit]
# Human readable name of the unit
Description=Python User Service
#Link it to bluetooth
After=bluetooth.service
Requires=bluetooth.service
PartOf=bluetooth.service
[Service]
# Command to execute when the service is started
ExecStart=/usr/bin/python3 /home/root/MyServ.py
# Disable Python's buffering of STDOUT and STDERR, so that output from the
# service shows up immediately in systemd's logs
Environment=PYTHONUNBUFFERED=1
# Automatically restart the service if it crashes
Restart=on-failure
# Our service will notify systemd once it is up and running
#Type=notify
Type=simple
# Use a dedicated user to run our service
User=root
[Install]
# Tell systemd to automatically start this service when the system boots
# (assuming the service is enabled)
WantedBy=default.target
On [Unit] section you can reload services
PropagatesReloadTo=, ReloadPropagatedFrom=
A space-separated list of one or more units where reload requests on this unit will be propagated to, or reload requests on the
other unit will be propagated to this unit, respectively. Issuing a
reload request on a unit
will automatically also enqueue a reload request on all units that the reload request shall be propagated to via these two settings.
It sends bluetoothd command to reload via dbus. Not kill daemon, just reread configuration.
Or on [Service] section
ExecStopPost=/usr/bin/systemctl restart bluetooth.service
Or use override.conf on bluetooth.service
systemctl edit bluetooth.service
And here put
[Unit]
BindsTo=MyServ.service

systemd After=nginx.service is not working

I am trying to setup a custom systemd service on my linux system and was experimenting with it
Following is my custom service, where it will trigger a bash file
[Unit]
Description=Example systemd service.
After=nginx.service
[Service]
Type=simple
ExecStart=/bin/bash /usr/bin/test_service.sh
[Install]
WantedBy=multi-user.target
Since I have mentioned After=nginx.service i was expecting nginx serivce to start automatically
So after starting the above service, i check the status of nginx, which has not started
However if i replace After with Wants it works
Can someone differenciate between After and Wants and when to use what?
Specifying After=foo tells systemd how to order the units if they are both started at the same time. It will not cause the foo unit to autostart.
Use After=foo in combination with Wants=foo or Requires=foo to start foo if it's not already started and also to keep desired order of the units.
So your [Unit] should include:
[Unit]
Description=Example systemd service.
After=nginx.service
Wants=nginx.service
Difference between Wants and Requires:
Wants= : This directive is similar to Requires= , but less strict. Systemd will attempt to start any units listed here when this unit is activated. If these units are not found or fail to start, the current unit will continue to function. This is the recommended way to configure most dependency relationships.

Systemd service failing on startup

I'm trying to get a nodejs server to run on startup, so I created the following systemd unit file:
[Unit]
Description=TI SensorTag Communicator
After=network.target
[Service]
ExecStart=/usr/bin/node /home/pi/sensortag-comm/sensortag.js
User=root
[Install]
WantedBy=multi-user.target
I'm not sure what I'm doing wrong here. It seems to fail before the nodejs script even starts, as no logging occurs. My script is dependent on mysql 5.5 (I think this is where I'm running into an issue). Any insight, or even a different solution would be appreciated.
Also, it runs fine once I'm logged into the system.
Update
The service is enabled, and is logging through journalctl. I'll update with the results on 7/11/16.
Not sure why it didn't work the first time, but upon checking journalctl the issue was 100% that MySQL hadn't started. I once again changed it to After=MySQL.service and it worked perfectly!
If there is no mention of the service at all in the output of journalctl that could indicate that the service was not enabled to start at boot.
Make you run systemctl enable my-unit-name before your next boot test.
Also, since you depend on MySQL being up and running, you should declare that with something like: After=mysql.service. The exact service name may depend on your Linux distribution, which you didn't state.
Adding User=root adds nothing, as system units would be run by root by default anyway.
When you said "it fails", you didn't specify whether it was failing at boot time, or with a test run by systemctl start my-unit-name.
After attempting to start a service, there should be logging if you run journalctl -u my-unit.name.service.
You might also consider adding StandardOutput=journal to your unit file to make sure you capture output from the service you are running as well.

Prevent service from starting

The idea is to create a keep-down.service that never starts:
[Unit]
Description=Keeps daemon down
Before=mydaemon.service
ConditionPathIsDirectory=/var/lib/dummy-never-existing-path
[Service]
ExecStart=/bin/true
[Install]
WantedBy=multi-user.target
So it's needed by the mydaemon.service. While keep-down.service is installed, the mydaemon.service can't start (theoretically).
Motivation:
no systemctl commands can start the mydaemon.service
no modifications to the mydaemon.service unit file
no messing with the config of the mydaemon.service
it's atomic: installing/removing the keep-down.service custom package
The problem is that mydaemon.service starts anyways. Why is that?
You have specified that your keep-down service must start before mydaemon.service:
Before=mydaemon.service
But you haven't actually configured any dependency between the two, such as:
RequiredBy=mydaemon.service
Details are in the systemd.unit man page, which for example says this about Before= and After=:
Note that this setting is independent of and orthogonal to the
requirement dependencies as configured by Requires=. It is a common
pattern to include a unit name in both the After= and Requires=
option, in which case the unit listed will be started before the
unit that is configured with these options.
However, all of this is really unnecessary. You can accomplish with you want using the systemctl mask command:
mask NAME...
Mask one or more unit files, as specified on the command line. This
will link these units to /dev/null, making it impossible to start
them. This is a stronger version of disable, since it prohibits all
kinds of activation of the unit, including enablement and manual
activation. Use this option with care. This honors the --runtime
option to only mask temporarily until the next reboot of the
system. The --now option can be used to ensure that the units are
also stopped.
So:
# systemctl mask mydaemon

Resources