Systemd timer for a bound service restarts the service it is bound to - service

I have two systemd services a and b, where b is "After" and "BindsTo" a, and b is a short command that is launched every minute with a systemd timer.
Heres my config:
$ cat /systemd/a.service
[Unit]
After=foo
BindsTo=foo
[Service]
ExecStart=/opt/a/bin/a
Group=lev
User=lev
Restart=Always
WorkingDirectory=/opt/a
$ cat /systemd/b.service
[Unit]
After=a
BindsTo=a
[Service]
ExecStart=/opt/b/bin/b
Group=lev
User=lev
WorkingDirectory=/opt/b
$ cat /systemd/b.timer
[Unit]
[Timer]
OnCalendar=*:0/1:00
When I run sudo systemctl stop a, service a is indeed stopped, but then it is started back up at the top of the next minute when the timer for service b runs b
The systemd documentation states that BindsTo
declares that if the unit bound to is stopped, this unit will be stopped too.
(https://www.freedesktop.org/software/systemd/man/systemd.unit.html#BindsTo=)
I expect that by stopping a, b will also be stopped, and the timer disabled. This is not the case. Can you help explain why the b timer restarts not only b (which should fail), but also a?
Can you also help me edit these services such that:
on boot, a is started first, then b is started
when I sudo systemctl stop a, b's timer does not run
when I sudo systemctl start a, b's timer begins running again
Thanks in advance!

Here are the simplest units that meet your constraints:
test-a.service
[Service]
ExecStart=sleep 3600 # long-running command
test-b.service
[Service]
ExecStart=date # short command
test-b.timer
[Unit]
After=test-a.service
BindsTo=test-a.service # makes test-b.timer stop when test-a.service stops
[Timer]
OnCalendar=* *-*-* *:*:00
[Install]
WantedBy=test-a.service # makes test-b.timer start when test-a.service starts
Don't forget to
systemctl daemon-reload
systemctl disable test-b.timer
systemctl enable test-b.timer
To apply the changes in the [Install] section.
Explanations:
what you want is to bind a.service with b.timer, not b.service
b.service is only a short command, and systemctl start b.service will only run the command, not start the associated timer
only systemctl start b.timer will start the timer
The WantedBy tells systemd to start test-b.timer when test-a.service starts
The BindsTo tells test-b.timer to stop when test-a.service stops
The After only ensures that test-b.timer is not started at the same time than test-a.service: it will force systemd to start test-b.timer after test-a.service has finished starting.
About the behaviour you observed:
When you stopped your a.service, the b.timer was still active and it tried starting b.service to run its short command. Since your b.service specified BindsTo=a.service, systemd thought that b.service required a.service to be started also, and effectively restarted a.service for b.service to run correctly.

I could be mistaken, but I believe that the "Restart=Always" option is the reason that the service named a is started and hence why the service named b is not subsequently stopped.
The man page for systemd.service states if this option is set to always
the service will be restarted regardless of whether it exited cleanly
or not, got terminated abnormally by a signal, or hit a timeout.
https://www.freedesktop.org/software/systemd/man/systemd.service.html#Restart=
So even though you are stopping the service, this option is starting it again.
You can test this by running the following commands. Since you have service "b" on a one minute timer, I would run the stop command at 10 seconds after the top of the minute (i.e. 10:00:10). Then I would run the status command 20 seconds later and see if the service has been restarted.
sudo systemctl stop a
sudo systemctl status a b

Related

Can't see my dbus object when program run from systemctl service

I have a cpp application which broadcasts an object and its methods on the dbus. I try to run this program at startup with the following service file:
[Unit]
Description=Running dbus program
After=network.target
[Service]
Type=simple
ExecStart=/home/my_name/Documents/dbus/build/my_app
StandardOutput=console+journal
StandardError=console+journal
[Install]
WantedBy=multi-user.target
After reloading:
systemctl daemon-reload
and running it:
sudo systemctl start my_service.service
I got no error in the journal, but I cant see anything on the dbus (running d-feet, and browsing for my object, I cant find anything)
Running the exact same ExecStart:
/home/my_name/Documents/dbus/build/my_app
in the console works fine.
What am I missing? Thanks!
As you want your service to run on the session bus you will need to use:
sudo systemctl --user start my_service.service
Putting the file into /etc/systemd/user/ location will make it available to all users still.

systemd not executing ExecStop script

I have created a service(name- develop) using systemd. Following is the content of my develop unit file -
Description=Develop Manager Service
[Service]
Type=forking
PIDFile = /home/nayasa/data/var/run/developPid
User=root
Group=root
ExecStartPre = /bin/bash /home/nayasa/control_scripts/develop_startPre.sh
ExecStart =/bin/bash /home/nayasa/control_scripts/develop_start.sh
ExecStop =/bin/bash /home/nayasa/control_scripts/develop_stop.sh
[Install]
WantedBy=multi-user.target
My develop.service forks multiple processes during runtime.
Whenever I run systemctl stop develop.service , systemd stops all processs in the CGroup of my develop service whereas the develop_stop script that I have provided only kills the main process using pid from pidfile. I want to stop only the main process. It seems to me that systemd is not using my stop script. How do I force systemd to execute my stop script to stop the service and not kill all processes of the Cgroup? FYI- I know that using KillMode option I can direct systemd to kill only main process and leave other processes, but I want to know why is my script not being executed?
It's a little weird to expect orphaned processes to persist after stopping a service. You would be left with a system that's in an unknown state. What would happen if you started the service again?
I think what you probably want is more complicated than a single service.
Let's say you wanted develop.service to launch proc1 and proc2. You want systemctl stop develop.service to kill proc1 but not proc2. In this case, you still need something to manage proc2 otherwise you have a rogue orphaned unmanaged and monitored process. The answer is to use another service.
Instead, try making two services. develop.service would launch proc1, possibly using your scripts. Then add a Wants=proc2.service to your [Unit] section. proc2.service would be responsible for proc2.
This means systemctl start develop.service will launch proc1 and proc2. Meanwhile systemctl stop develop.service will only kill proc1. proc2 can still be stopped/monitored by inspecting proc2.service.

respawn service Debian Jessie without inittab

I've installed the last stable version of Debian (Jessie) and /etc/inittab doesn't exist. I have read the new init system is called Sysv.
I need to launch a service with parameter, I used to add a line in inittab like
u1:23:respawn:/etc/init.d/my_service foreground
I'm trying to add this one with sysvrc-conf -p but I don't know how...
How can I do that without inittab?
Thank you so much.
Found this question by google, maybe someone else finds this usefull: The new init system for Debian Jessie is systemd. The old way in Debian Wheezy was Sysv with /etc/inittab.
To create a respawn service with systemd just create a file in /etc/systemd/system/ i.e. mplayer2.service
[Unit]
Desription=mplayer with systemd, respawn
After=network.target
[Service]
ExecStart=/usr/bin/mplayer -nolirc -ao alsa -vo null -really-quiet http://stream.sunshine-live.de/hq/mp3-128/Facebook-og-audio-tag/
Restart=always
[Install]
WantedBy=multi-user.target
and activate it
systemctl enable mplayer2.service
reboot or start it manually
systemctl daemon-reload
systemctl start mplayer2.service
If you reboot or kill the process, it will be restarted automatically some seconds later.

Docker and systemd - service stopping after 10 seconds

I'm having trouble getting a Docker container to stay up when it's started by systemd. When I start it manually with sudo docker start containername, it stays up without trouble, but when it's started via systemd with sudo systemctl start containername, it stays up for 10 seconds then mysteriously dies, leaving messages in syslog something like the following:
Mar 13 14:01:09 hostname docker[329]: time="2015-03-13T14:01:09Z" level="info" msg="POST /v1.17/containers/containername/stop?t=10"
Mar 13 14:01:09 hostname docker[329]: time="2015-03-13T14:01:09Z" level="info" msg="+job stop(containername)"
I am making the assumption that it's systemd killing the process, but I can't work out why it might be happening. The systemd unit file (/etc/systemd/system/containername.service) is pretty simple, as follows:
[Unit]
Description=MyContainer
After=docker.service
Requires=docker.service
[Service]
ExecStart=/usr/bin/docker start containername
ExecStop=/usr/bin/docker stop containername
[Install]
WantedBy=multi-user.target
Docker starts fine on boot, and it looks like it does even start the docker container, but no matter if on boot or manually, it then quits after exactly 10 seconds. Help gratefully received!
Solution: The start command seems to need the -a (attach) parameter as described in the documentation when used in a systemd script. I assume this is because it by default forks to the background, although the systemd expect daemon feature doesn't appear to fix the issue.
from the docker-start manpage:
-a, --attach=true|false
Attach container's STDOUT and STDERR and forward all signals to the process. The default is false.
The whole systemd script then becomes:
[Unit]
Description=MyContainer
After=docker.service
Requires=docker.service
[Service]
ExecStart=/usr/bin/docker start -a containername
ExecStop=/usr/bin/docker stop containername
[Install]
WantedBy=multi-user.target

Centos Service not starting

Running Centos7, I have init.d service that I'm trying to start. When I do so it comes back with an OK message which = success. Yet when I use TOP I don't see it running.
Now if I take the command that the service should be running from the cat /etc/init.d/XXXX it starts as expected.
How can I go about debugging this? I've checked /messages, and /secure and even dmesg but I don't see anything amiss.
Try systemctl start <command>
Eg if you want to start ssh
systemctl start sshd
or
systemctl start sshd.service
Look for man pages of systemctl
Explaination
CentOS 7 / RHEL 7 / Fedora Linux (many other modern distor) uses Systemd. It is a system and service manager for Linux operating systems. In newer distro such as CentOS7/RHEL7 systemd replaces Upstart as the default init system
In case you have scripts for starting & stopping of a particular process or code
you can place a file /etc/init.d/ directory
with somewhat below logic
#!/bin/bash
SCRIPT_PATH=/pathtoscriptdirectory
case $1 in
start)
sh $SCRIPT_PATH/startup.sh
;;
stop)
sh $SCRIPT_PATH/shutdown.sh
;;
restart)
sh $SCRIPT_PATH/shutdown.sh
sh $SCRIPT_PATH/startup.sh
;;
esac
exit 0
Its good practice to make start stop restart blocks, you can have your custom blocks too
Also make sure that you have executable permission over all the files in this lineup
Then run it like you run the normal services