Skip to content
Advertisement

Linux display command works in terminal, but not in systemd service

I made a web app to turn off my computer’s screens, there are a few different technologies but it’s fairly simple:

I have a html/js frontend that detects a button click (Screens On / Screens Off) which sends the option to the PHP backend via ajax

The php then connects over a tcp port, sending the option to a program written in golang

Then my golang program executes the command to turn off/on the screens. The command it runs is (“xset -display :0 dpms force off”)

The problem I’m having is that the command only works when im running the golang program in the terminal, but when i set it up as a service the command wont work.

This is the golang code:

JavaScript

And relevant PHP code:

JavaScript

I used systemd to set up the service, so after building the program and placing it in /usr/bin/

JavaScript

I can run the screenControl program in the terminal, and select “screens off” in the web app and it all works as expected:

JavaScript

I then created a systemd unit file (/etc/systemd/system/screenControl.service):

JavaScript

I started the service and checked it:

JavaScript

So it’s running, but then when I select screens off in the web app now, nothing happens… I checked the service status again and it is receiving the message to turn the screens off but the command is exiting with an error:

JavaScript

What’s the problem here and how can I get that command to work as a service? Once this is working I want to have the service start automatically when the machine turns on, although with systemd I think that’s as simple as:

JavaScript

Any help would be great, thank you 🙂

Edit

After having the golang program show me the stderr of the xset command, I now also have the error message:

JavaScript

Advertisement

Answer

As per David Budworth’s comment, the fix was exceedingly simple; as the service was running under root, it didn’t have the DISPLAY environment variable set.

In go you can set the environment variables when using exec like so:

JavaScript

And from James Henstridge answer I found I also needed to run xhost +SI:localuser:root to allow the root user access to the X server.

You can do this for users after they’ve logged in by adding this line to the top of the /etc/profile file

JavaScript

OR

You can get it to work even when no user is logged in (when the login screen is showing)

First I created the directory /opt/scripts then created the file /opt/scripts/xhost.sh and gave it executable permissions with chmod +x /opt/scripts/xhost.sh

In this file is just the one line:

JavaScript

Then edit the file /etc/lightdm/lightdm.conf (I had to create it, but edit it if it’s there) and add the line display-setup-script=/opt/scripts/xhost.sh

So my lightdm.conf file looks like this:

JavaScript

This tells LightDM (the display manager running in Ubuntu) to run the script /opt/scripts/xhost.sh after the X server is started but before anything else, therefore root is given the xhost authorization straightaway!

note:

display-setup-script is run after the X server starts but before the user session / greeter is run. Set this if you need to configure anything special in the X server. It is run as root. If this command returns an error code the X server is stopped. Source: https://wiki.ubuntu.com/LightDM

User contributions licensed under: CC BY-SA
3 People found this is helpful
Advertisement