Generate/inject systemd unit files from script/program - shell

How can I inject/generate systemd unit (service) files from a script or program, for example a Bash-script or Python-script?
Should I use a library (in e.g. Python) (which library?) or should I create raw unit files in the filesystem and then use the systemctl command? Is a systemctl daemon-reload necessary? Maybe the systemd C-API supports this?
Is it a good pattern/practice? Should I develop an application that is started by systemd which then starts the commands, this means: Should I outsource the starting-procedure to my application or should I left that at systemd?

Related

Centos 7 Created service to run shell script on infinite loop

I have the following script:
whie true
do
#code
sleep 60
done
I then wanted to create a service to start the machine and launch this script as service:
created my.service at /etc/systemd/system/my.service
[Unit]
Description=my Script
[Service]
Type=forking
ExecStart=/bin/script.sh
[Install]
WantedBy=multi-user.target
problem occurs when i systemctl start my.service
it goes to while true loop and hang in there, how can i run this service and make it run in the background ?
According to systemd specification at link. Type=forking is not exactly correct kind of start-up in your case
If set to forking, it is expected that the process configured with
ExecStart= will call fork() as part of its start-up. The parent
process is expected to exit when start-up is complete and all
communication channels are set up. The child continues to run as the
main service process, and the service manager will consider the unit
started when the parent process exits. This is the behavior of
traditional UNIX services. If this setting is used, it is recommended
to also use the PIDFile= option, so that systemd can reliably identify
the main process of the service. systemd will proceed with starting
follow-up units as soon as the parent process exits.
The Type=simple can be correct one. You can try with it
If set to simple (the default if ExecStart= is specified but neither
Type= nor BusName= are), the service manager will consider the unit
started immediately after the main service process has been forked
off. It is expected that the process configured with ExecStart= is the
main process of the service. In this mode, if the process offers
functionality to other processes on the system, its communication
channels should be installed before the service is started up (e.g.
sockets set up by systemd, via socket activation), as the service
manager will immediately proceed starting follow-up units, right after
creating the main service process, and before executing the service's
binary. Note that this means systemctl start command lines for simple
services will report success even if the service's binary cannot be
invoked successfully (for example because the selected User= doesn't
exist, or the service binary is missing).

How to properly override generated systemd unit file to start after a ZFS mount has mounted

I'm using Ubuntu 18.04.4 LTS which uses systemd, but the squid package packaged with this version of Ubuntu is configured to start via init.d. It starts and runs via systemctl start squid.service if I start it manually after the system has booted.
However, I'm using a ZFS mount point ("/media") to store the cache data, and during the boot process squid is starting before this mount point is active. Consequently I'm getting the error "Failed to verify one of the swap directories". Full output of systemctl status squid is here
I'd like to tell systemd to wait until after media.mount has completed in the most minimally invasive way possible (e.g. without modifying the /etc/init.d/squid file that is maintained by the package). To that end I created the /etc/systemd/system/squid.service.d/override.conf file like so:
% cat /etc/systemd/system/squid.service.d/override.conf
[Unit]
Wants=network.target network-online.target nss-lookup.target media.mount
After=network.target network-online.target nss-lookup.target media.mount
[Install]
WantedBy=multi-user.target
But squid is still starting too early.
Is what I want to do possible? Or do I have to bite the bullet and define a native /etc/systemd/system/squid.service file and remove the /etc/init.d/squid init script?

Running a binary as systemd service does not work

I have a go project and when I compile it I get your typical binary. If I call the binary directly from the command line with the adequate inputs, it runs perfectly well. I want to make this program part of the systemd ecosystem and the following is my my gobinary.service
[Unit]
Description=Run Go Service
[Service]
WorkingDirectory=/path/to/directory/
ExecStart=/path/to/directory/binary --config config/service.conf
Restart=always
[Install]
WantedBy=multi-user.target
I can start and stop the service using the usual sudo service gobinary start without error messages but the problem is that the program is actually not running because it does not respond to the inputs, namely it has a rabbitmq input queue, despite me sending content to the queue it doesn't react. If however I run the program using the binary directly $ ./binary --config/service.conf everything runs smoothly. How do I troubleshoot this?

Running systemd unit directly after local-fs.target and before basic.target

I am creating an embedded system. The embedded system mounts a partition. Directly after mounting the partition, I need to prep an encrypted folder (encfs). I need this to run before any other multi-user.target or graphical.target
Here is my unit file, which works by it's self.
[Unit]
Description=Mx Encrypted Folder
[Service]
Type=oneshot
ExecStart=/usr/bin/mxmountencrypted
RemainAfterExit=true
ExecStop=/usr/bin/mxunmountencrypted
This unit file has no dependencies defined, currently.
Again, I need:
To run this directly after mounting file systems (local-fs.target)
Before any multi-user.target or graphical.target, where must of the services that depend on it will be ran.
It must stop fully before stopping local-fs.target, since there will be a nested mount that needs to be unmounted before systemd can unmount the partition.
I looked into using the systemd.mount item, but it doesn't support encfs.
Based on what you have listed in the requirements:
[Unit]
Description=Mx Encrypted Folder
Requires=local-fs.target
After=local-fs.target
[Service]
Type=oneshot
ExecStart=/usr/bin/mxmountencrypted
RemainAfterExit=true
ExecStop=/usr/bin/mxunmountencrypted
[Install]
WantedBy=multi-user.target
More on systemd Unit files here: https://www.freedesktop.org/software/systemd/man/systemd.unit.html
and systemd Service files: https://www.freedesktop.org/software/systemd/man/systemd.service.html

Spring Boot application as a systemd service: log file

I know it is possible to create a jar from Spring Boot application which can be used as a systemd service. I used this manual to create systemd service from my application on Debian Jessie OS. Eveyrthing works fine, but I can't find a way how to write logs to separate file insted of /var/syslog. As documentation says:
Note that unlike when running as an init.d service, user that runs the
application, PID file and console log file behave differently under
systemd and must be configured using appropriate fields in ‘service’
script. Consult the service unit configuration man page for more
details.
it should be configured in *.service file, but I can't find any appropriate options. Has someone any experience in this question?
Run the service with a sh process
[Service]
ExecStart=/bin/sh -c "/var/myapp/myapp.jar >> /var/logs/myapp.log"
KillMode=control-group
See this discussion in influxdb github repo https://github.com/influxdata/influxdb/issues/4490

Resources