systemd After=nginx.service is not working - linux

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.

Related

Nitrogen through systemd services doesn't work

I am writing a tool (zxcV32/OpenRWC) that fetches wallpapers from Reddit and sets them to the monitor(s) using nitrogen.
To make it easy to install and run automatically, I have created a deb package and a systemd service.
When the service is started using
sudo systemctl start openrwc#$USER.service
nitrogen errors out with exit status 1. (No other error message). And yes, the exec installed by the deb package works fine when manually run from the terminal.
I have compared that the command run by the tool is precisely the same when run through the systemd service or terminal run.
Sample command
nitrogen --set-scaled /home/zxcv32/.config/OpenRWC/fz41kmzk1wj91.jpg --head=0
Service
[Unit]
Description=Reddit Wallpaper Changer for GNU/Linux
Requires=display-manager.service
After=display-manager.service
StartLimitIntervalSec=0
[Service]
Type=simple
ExecStart=/usr/bin/openrwc
Restart=always
RestartSec=5
User=%i
[Install]
WantedBy=graphical.target
What may be wrong with the service? I want the service to be the user's choice, if they want to run it or not.
BTW I found this question that claims that nitrogen works through a service. (maybe there is a difference between running nitrogen directly through system service and through a go funciton)
System: Debian 11 5.10.0-17-amd64
Found the issue.
Systemd does not have access to certain environment variables.
DISPLAY environment variable needs to be set in the openrwc#.service.
[Service]
Environment="DISPLAY=:0"

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 run an app as a daemon with systemd?

I'd like to run syncthing as a daemon, trying to follow this hint here from the syncthing manual.
I'm running on Fedora 25 and syncthing 0.14.24.
The executable is pointed to via a symlink in /usr/bin/syncthing which can be executed by any user (tested this successfully).
To enable the service, I'm typing (myuser is replaced with my actual username in all of the below):
sudo systemctl enable sycnthing#myuser.service
Which returns:
Failed to lookup unit file state: Invalid argument
I don't understand what the error message means. How could I get to run syncthing as a daemon?
syncthing#myuser.service:
[Unit]
Description=Syncthing - Open Source Continuous File Synchronization for %I
Documentation=man:syncthing(1)
After=network.target
Wants=syncthing-inotify#myuser.service # I also commented this line out; didn't have an effect
[Service]
User=%i
ExecStart=/usr/bin/syncthing -no-browser -no-restart -logflags=0
Restart=on-failure
SuccessExitStatus=3 4
RestartForceExitStatus=3 4
[Install]
WantedBy=multi-user.target
I think myuser should be substituted for your actual username.
Arch wiki has a pretty good article:
System service
Running Syncthing as a system service ensures that it is running at startup even if the user has no active session, it is intended to be used on a server.
Enable and start the syncthing#myuser.service where myuser is the actual name of your user.
Credit: https://wiki.archlinux.org/index.php/Syncthing

Systemctl dependency failure, stop dependent services

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.

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.

Resources