How can I launch a script in a terminal window from a service
I have two scripts which together allow me to receive and answer phone calls over serial. The first is what I want to run as a service in the background it checks if there is a RING signal and if there is then open a terminal window with the second script running.
They both use python3, the first script is:
while True:
if (ser.inWaiting() > 0):
x = ser.readline()
if (x == b'RINGrrn'):
os.system("gnome-terminal -- python3 /home/user/answer.py")
exit()
The main part of the second is:
os.system("clear")
print("Incoming Call")
PU = input("Press Enter To Pick Up")
send_at('ATA' + ';','OK',1)
os.system("clear")
print("ON CALL")
HU = input("Press Enter To Hang Up")
send_at("AT+CHUPrn" + ';','OK',1)
os.system("clear")
print('Call Ended')
time.sleep(3)
os.system("clear")
os.system("gnome-terminal -- python3 /home/user/ring.py")
os.system("exit")
If I run the first in an open terminal just as "python3 ring.py" it works fine but leaves me with a constant open terminal.
What I want is to run Ring.py as a service or a background process that just launches Answer.py as it’s called.
I tried using a .service file, enabled and started it, htop showed that it was running Ring.py but it wouldn’t launch Answer.py in a terminal window. There’s no error code it just doesn’t show up.
This is the service file:
[Unit]
Description=Detect Incoming Calls
[Service]
Type=simple
User='my username'
ExecStart= /usr/bin/python3 /home/user/Ring.py
Restart=always
[Install]
WantedBy=multi-user.target
How can I get this to work the way I want? Or what am I doing wrong?
gnome-terminal
is a user GUI application and it requires a display server user session up and running first and then, the service launching it will require certain environment variables set and/or proper authentication/permissions granted.
You can specify those environment variables in a system service by for example setting the address to the display server, but that can change and you might need to set it again and there is more to launching a GUI user application from systemd
than just specifying those variables, so this is not recommended and a user service is the way to go IMO.
Therefore, you need to setup your service as a user-service in order to interact with your user-session environment by default as the environment variables like $DISPLAY
will be automatically inherited by a user service.
To do that you need to, first, place your unit/service file either under /usr/lib/systemd/user/
or under ~/.config/systemd/user/
in your user’s home.
Then, inform systemd
about it without needing to reboot like so:
systemctl --user daemon-reload
Then, enable and start and manage it with the --user
flag and without sudo
like so:
systemctl --user enable unit-name
And:
systemctl --user start unit-name
You will always need to use the --user
flag to manage it from now on … for example:
systemctl --user status unit-name
Or:
systemctl --user restart unit-name
Or:
systemctl --user stop unit-name
Notice:
You don’t need to specify a user/group for the user service as it will run as your current logged-in user by default.
You might, also, want to change Restart=always
to Restart=on-failure
to avoid running multiple instances of your script if status reporting is not set from your script as it appears.
You might, as well, want to change WantedBy=multi-user.target
under [Install]
section to WantedBy=default.target
or similar graphical user target.