Search code examples
pythonsystemddbusgnome-terminal

How to launch gnome-terminal from dbus plugin, a systemd service, using Python


I use Python to develop a simple dbus based plugin (dbus.service.Object) that takes IPC calls from a command-line script. The dbus service is configured to host in systemd. It is running as expected. However, when I add a capability in the plugin to launch a gnome-terminal it failed. It seems the execution is stuck in any of these subprocess calls, no matter it is call() or Popen(). Wonder how can I make the plugin launch gnome-terminal correctly?

#subprocess.call(['gnome-terminal', '--', '/bin/bash', '-c', 'ls', '-al', '&'])
#subprocess.call(['systemd-run', '--user', '--service-type=forking', 'gnome-terminal', '-t', "Test",'--','/bin/bash', '-c', 'ls', '-al', "&"])
#subprocess.call(['DISPLAY=:0', 'gnome-terminal', '--', '/bin/bash', '-c', 'ls', '-al', '&'])

Things I also tried to launch a python script from the plugin and have the script to launch gnome-terminal but still failed.

Fail means that the terminal does not open and the ps doesn't show terminal. I also tried with os.system. It works if running directly from a console.

os.system('gnome-terminal -- /bin/bash -c "python /data/scripts/test.a.1.py -f /data/station_profile_A.json"')

The journal log shows the error below:

Dec 21 09:34:20 ubuntu coordinator[5380]: Unable to init server: Could not connect: Connection refused Dec 21 09:34:20 ubuntu coordinator[5380]: # Failed to parse arguments: Cannot open display:

If I add 'DISPLAY=:0' in front of gnome-terminal, it doesn't help.


Solution

  • To connect to X, you need to set both DISPLAY and XAUTHORITY.

    For example XAUTHORITY=$HOME/.Xauthority and DISPLAY=:0.0.

    The file named by XAUTHORITY must be readable. The file is mode 0600.

    I would suggest that you have your DBUS API include handing over a copy of the magic cookie, the contents of the XAUTHORITY file, to the service which then would write it to a temporary file and then with DISPLAY and XAUTHORITY set would run the command.