Linux – How best to start the systemd service to run multiple apps

linuxprocessservicessystemd

I have a one-shot service that calls a script in /usr/

Here my .service file:

[Unit]
Description = Start apps
After = network.target

[Service]
Type=simple
ExecStart=/usr/start_apps.sh

[Install]
WantedBy=multi-user.target

My script does somthing like:

cd /home/user/apps
# Run apps one at a time in background
./app1 &
./app2 &

Now this appears to try to run these apps, but when I do pgrep app there is nothing running.

So, I assuemed this is because the service has ended. So I tried a different approach:

cd /home/user/apps
# Run app1 in back ground 
./app1 &
# Run app2 in forground so the service does not stop
./app2

Now this works (pgrep shows me the apps are running) – but when I start the service it never returns I have to do ctrl+c and then I can get back to the bash prompt and the apps are both still running.

What I want is to start the service, have both apps run and then return to the command line all by doing just:

systemctl start my-service.service

What is the best way to do this?

update I am installing my service like this:

systemctl stop my-service.service
 ... copy the service/script files in place...
systemctl daemon-reload
systemctl enable my-service.service
systemctl start my-service.service

not sure… but it might be relavant?

Best Answer

Starting all the processes in background should work, but then you need to use Type=forking and you'll probably want to use a few more options, in particular RemainAfterExit=yes is probably important.

That use case is similar to the handling of an rc.local script, which is handled in systemd through this unit template, so perhaps using all those options would be a good idea:

[Service]
Type=forking
ExecStart=/usr/start_apps.sh
TimeoutSec=0
RemainAfterExit=yes
GuessMainPID=no

I'm not sure why you're getting blocked and having to hit Ctrl+C on the case where you have the last process in foreground... Do you have to hit Ctrl+C on the systemctl start command itself? I'd say that's a bit odd...

Please note that starting apps this way (many of them in background, from a script) is not really how systemd is intended to be used and you'll be missing out on features. For instance systemctl stop or systemctl restart will most likely not work at all on that unit.

These days, running apps in background is seen as a "hack" (not only by systemd but by many of its precursors and most other modern service managers.) While systemd is still able to do that, that support is there mostly for backwards compatibility and is not intended to be used when better alternatives exist.

My recommendation would be that you create separate services for each app, or perhaps use template units if you're starting many instances of the same process. Also look into directives to specify dependencies between units so they start and stop in the correct order. In particular, take a look at the PartOf= directive, which allows you to manage a group of services as a single unit, allowing you to start, stop or restart them all together with a single command.