Home > Enterprise >  systemctl --user fails within a webapp or user su session
systemctl --user fails within a webapp or user su session

Time:07-16

I have a web app that at a certain point the user can restart another web app, both running on apache-tomcat servers, both running under the same user.

Web app 1, let's call it manager, is used to stop and start web app 2, let's call it app-server.

Both tomcat servers are running as a user service, with the unit files located in /etc/systemd/user/.

While installing these two tomcat servers, through some bash scripts, I made sure to run loginctl enable-linger user. In those scripts, I'm able to run systemctl --user but only after setting the following variables on a here document and running everything inside it:

#!/bin/bash

(...)

su user << 'EOF'

export XDG_RUNTIME_DIR=/run/user/$(id -u user)
export DBUS_SESSION_BUS_ADDRESS=/run/user/$(id -u user)/bus

systemctl --user ...

EOF

(...)

You can check how I dealt with this on another question of mine, here: https://superuser.com/q/1730397/1708440

Now, the problem that I'm facing is when trying to stop or start the app-server service with systemctl --user stop app-server.

Both web apps are Java applications, so to stop and start the services I'm doing:

Process p = Runtime.getRuntime().exec("systemctl --user start app-server");

I've also tried:

String[] commands = {"bin/sh","-c","export XDG_RUNTIME_DIR=/run/user/$(id -u user)",
"export DBUS_SESSION_BUS_ADDRESS=/run/user/$(id -u user)/bus","systemctl --user start app-server"}
Process p = Runtime.getRuntime().exec(commands);

In both cases, it outputs:

Failed to connect to bus: No such file or directory

I've also noticed that if I run the start command after su user, the output is the same but only if I do not set the environment variables.

I can see that linger is enabled for the user after running loginctl user-status and I can also see the /lib/systemd/systemd --user process running for that user.

So, my question is: How can I achieve the start and stop of a user service within a Java web app that is running on a Tomcat server?

CodePudding user response:

After a lot of trial and error I finally found the solution:

I am now able to achieve my goal with:

String[] commands = {"/bin/sh","-c","export XDG_RUNTIME_DIR=/run/user/$(id -u user) 
&& systemctl --user start app-server"}
Process p = Runtime.getRuntime().exec(commands);

Turns out I was on the right track, just missing a linking point.

The difference from my initial approach is the "&&" (and operator) on the command, to make sure that the systemctl --user is only executed after the variable has been set.

In the meantime I also found out that I only need to set XDG_RUNTIME_DIR.

  • Related