Python service gets repoprted as succeeded even though it has failed - python

I am running service on the raspberry pi that is meant to run a python script on the startup. Sometimes the python script fails, however when it fails the service still reports it as success which is wrong.
The python script below:
import cec
import sys
import time
import configparser
from tuya.devices import TuyaSmartSwitch
class SmartSwitch:
def __init__(self, config_path):
CONFIG = configparser.ConfigParser()
CONFIG.read(config_path)
try: # connect to the smart switch
self.device = TuyaSmartSwitch(
username=CONFIG["TUYA"]["username"],
password=CONFIG["TUYA"]["password"],
location=CONFIG["TUYA"]["location"],
device=CONFIG["TUYA"]["device"])
except:
print("Could not connect to the switch")
sys.exit()
def turn_off(self):
self.device.turn_off()
def turn_on(self):
self.device.turn_on()
This is the terminal output:
pi#raspberrypi:~/subwoofer_switch $ sudo systemctl status subwoofer.service
● subwoofer.service - My script to control suboowfer smart switch
Loaded: loaded (/etc/systemd/system/subwoofer.service; enabled; vendor preset: enabled)
Active: inactive (dead) since Thu 2020-07-02 19:46:43 BST; 23h ago
Process: 541 ExecStart=/usr/bin/python3 /home/pi/subwoofer_switch/subwoofer_control.py (code=exited, status=0/SUCCESS)
Main PID: 541 (code=exited, status=0/SUCCESS)
Jul 02 19:46:30 raspberrypi systemd[1]: Started My script to control suboowfer smart switch.
Jul 02 19:46:43 raspberrypi python3[541]: Could not connect to the switch
Jul 02 19:46:43 raspberrypi systemd[1]: subwoofer.service: Succeeded.
As you can see the script did fail the connection and sys.exit() should have run and closed the script but it still reports as success.
Here is the service code:
[Unit]
Description=My script to control suboowfer smart switch
After=multi-user.target
[Service]
Restart=on-failure
RestartSec=10s
Type=idle
ExecStart=/usr/bin/python3 /home/pi/subwoofer_switch/subwoofer_control.py
[Install]
WantedBy=multi-user.target
I am not sure what I am doing wrong, as my hope was if the service has failed to start it would try again to run the python script

If, as in your code, no parameter is supplied to sys.exit(), it defaults to zero, which means "success". So, if your intention is to exit with failure, use:
sys.exit(1)

Related

How do I debug a exit-code failure for the specific service for my app?

I'm trying to run a Flask app through Apache. When I run
systemctl list-units --type=service
I see that the unit for this specific app, "SITENAME.service" has failed.
When I run
sudo systemctl status SITENAME.service
I
get an error saying:
Loaded: loaded (/etc/systemd/system/SITENAMEenv.service; enabled; vendor preset: enabled)
Active: failed (Result: exit-code) since Sun 2023-01-01 21:26:25 UTC; 1min 1s ago
Process: 787 ExecStart=/home/ubuntu/SITENAME/SITENAMEenv/bin/uwsgi --ini SITENAMEenv.ini (code=exited, status=1/FAILURE)
Main PID: 787 (code=exited, status=1/FAILURE) Jan 01 21:26:25 ip-172-31-88-10 systemd[1]:
SITENAME.service: Main process exited, code=exited, status=1/FAILURE Jan 01 21:26:25 ip-172-31-88-10 systemd[1]: SITENAME.service: Failed with result 'exit-code'.
Where can I get more information on this failure? I can't tell if this is a python issue in the actual application code, or something else.
The site stopped working a little while ago, but there were no major changes to the code. The service that is not working has the description "uWSGI instance to serve SITENAME"

How to figure out why systemd service failed with result 'exit-code'?

I've created a python script that collects info for a 5 minute period and then sends data to aws cloudwatch. The body of the script runs forever in a while True: block, and when I run it on its own using python3 to_cloud.py, it functions successfully.
I made a service for it as follows:
[Unit]
Description=Service for sending script data to cloudwatch
After=multi-user.target
Conflicts=getty#tty1.service
[Service]
Type=simple
ExecStart=/usr/bin/python3 /home/ubuntu/scripts/to_cloud.py
WorkingDirectory= /home/ubuntu/scripts
StandardInput=tty-force
[Install]
WantedBy=multi-user.target
When I start the service, it runs for the duration of the internal loop that collects the info, but then the following happens:
● to_cloud.service - Service for sending script data to cloudwatch
Loaded: loaded (/lib/systemd/system/to_cloud.service; enabled; vendor preset: enabled)
Active: failed (Result: exit-code) since Wed 2021-06-23 16:53:44 UTC; 5s ago
Process: 191072 ExecStart=/usr/bin/python3 /home/ubuntu/scripts/to_cloud.py (code=exited, status=1/FAILURE)
Main PID: 191072 (code=exited, status=1/FAILURE)
Jun 23 16:52:43 ip-172-31-19-11 systemd[1]: Started Service for sending script data to cloudwatch.
Jun 23 16:53:44 ip-172-31-19-11 systemd[1]: to_cloud.service: Main process exited, code=exited, status=1/FAILURE
Jun 23 16:53:44 ip-172-31-19-11 systemd[1]: to_cloud.service: Failed with result 'exit-code'.
There are no logs in the journalctl so I'm wondering how to figure out what's going wrong. Thanks!

Python systemd service stops soon after started

I tried to run a Python script as a system service, but the service is not starting. Here is my configuration:
pyntp.service:
[Unit]
Description=Python NTP Service
After=multi-user.target
[Service]
Type=forking
ExecStart=/usr/bin/python $HOME/ntp/ntpservice.py
[Install]
WantedBy=multi-user.target
ntpservice.py:
#!/usr/bin/python
import os
import time
import json
pid = os.fork()
if pid == 0:
print 'parent'
else:
print 'child'
while True:
print('123')
time.sleep(1)
The step to start the service is as follows:
cp pyntp.service /etc/systemd/system/
cp ntpservice.py /usr/local/bin/
systemctl daemon-reload
systemctl enable pyntp.service
systemctl start pyntp.service
The thing is, when I try to see the status of pyntp service, it is always like this:
● pyntp.service - Python NTP Service
Loaded: loaded (/usr/lib/systemd/system/pyntp.service; enabled; vendor preset: disabled)
Active: inactive (dead) since Wed 2018-11-14 22:27:56 CST; 34min ago
Process: 801 ExecStart=/usr/bin/python $HOME/ntp/ntpservice.py (code=exited, status=0/SUCCESS)
Main PID: 801 (code=exited, status=0/SUCCESS)
Nov 14 22:27:56 HES1 systemd[1]: Started Python NTP Service.
Nov 14 22:27:56 HES1 systemd[1]: Starting Python NTP Service...
Can any one help me resolve this? Thanks.
Your program is behaving as expected. Just forking isn't enough to make a daemon. What's happening is your code is running as long as its parent process runs, then (both forks are) exiting when the parent process terminates. What you want is to write a daemon (and have that controlled by systemd). You may find this question useful in explaining some easy ways to do that: How do you create a daemon in Python?
fork is an important part of this process but just doing a fork by itself doesn't completely solve the problem. If you'd like to see a more detailed example of how to daemonize your process by hand using fork you can read this: Python code to Daemonize a process?

Run Python program as service on Ubuntu 16.04 inside a virtual environment

I'm trying to get a Flask + SocketIO app running as a service on Ubuntu 16.04, inside a virtual environment. My server is restarted every day at 3 am (outside of my control), so I need it to automatically launch on startup.
Running the script by itself works fine:
$ python main.py
(29539) wsgi starting up on http://127.0.0.1:8081
I can tell that it's working because it's serving pages (through an nginx server set up by following this Stack Overflow answer, though I don't think that's relevant.)
Here's my /etc/systemd/system/opendc.service:
[Unit]
Description=OpenDC flask + socketio service
[Service]
Environment=PYTHON_HOME=/var/www/opendc.ewi.tudelft.nl/web-server/venv
Environment=PATH=$VIRTUAL_ENV/bin:$PATH
ExecStart=/var/www/opendc.ewi.tudelft.nl/web-server main.py
Restart=always
[Install]
WantedBy=multi-user.target
So when I try to get that going using:
$ sudo systemctl daemon-reload
$ sudo systemctl restart opendc
It doesn't serve pages anymore. The status shows:
$ sudo systemctl status opendc
* opendc.service - OpenDC flask + socketio service
Loaded: loaded (/etc/systemd/system/opendc.service; enabled; vendor preset: enabled)
Active: inactive (dead) (Result: exit-code) since Fri 2016-08-19 10:48:31 CEST; 15min ago
Process: 29533 ExecStart=/var/www/opendc.ewi.tudelft.nl/web-server main.py (code=exited, status=203/EXEC)
Main PID: 29533 (code=exited, status=203/EXEC)
Aug 19 10:48:31 opendc.ewi.tudelft.nl systemd[1]: opendc.service: Service hold-off time over, scheduling restart.
Aug 19 10:48:31 opendc.ewi.tudelft.nl systemd[1]: Stopped OpenDC flask + socketio service.
Aug 19 10:48:31 opendc.ewi.tudelft.nl systemd[1]: opendc.service: Start request repeated too quickly.
Aug 19 10:48:31 opendc.ewi.tudelft.nl systemd[1]: Failed to start OpenDC flask + socketio service.
I've looked up (code=exited, status=203/EXEC) and done some troubleshooting with what I found:
I checked that main.py is executable:
$ ls -l main.py
-rwxr-xr-x 1 leon leon 2007 Aug 19 10:46 main.py
And that main.py has this first line to point to Python in the virtual environment:
#!/var/www/opendc.ewi.tudelft.nl/web-server/venv/bin/python
So what's the problem here?
Tried and tested way of making a python file run in a Virtual Environment as a service.
[Unit][Unit]
Description=Your own description
After=network.target
[Service]
Type=simple
Restart=always
WorkingDirectory=/home/path/to/WorkingDirectory/
VIRTUAL_ENV=/home/path/to/WorkingDirectory/venv
Environment=PATH=$VIRTUAL_ENV/bin:$PATH
ExecStart=/home/path/to/WorkingDirectory/venv/bin/python app.py
Restart=on-failure
[Install]
WantedBy=multi-user.target
I am putting this one here so I can always come back to it
I believe that you mistype PYTHON_HOME and than PATH=$VIRTUAL_ENV/bin:$PATH
you should use PATH=$PYTHON_HOME/bin:$PATH

Install python package for root user use

I've read all over, and I still can't get my python script to run in systemd.
Here is the shell script I use:
#! /bin/sh
cd /home/albert/speedcomplainer
/usr/bin/python speedcomplainer.py
I can execute the script (/usr/bin/speedcomplainer), it runs just fine from the command line. The python script loops forever, checking my internet speeds. As I said, it runs fine, from the command line directly (python ...) or from the shell script I created in usr/bin.
But when I put it into this unit file:
# speedcomplianer - checks and tweets comcast speeds.
#
#
[Unit]
Description=Ethernet Speed Complainer
After=syslog.target network.target
[Service]
Type=simple
WorkingDirectory=/home/albert/speedcomplainer
ExecStart=/usr/bin/speedcomplainer
Restart=always
StandardOutput=syslog
StandardError=syslog
[Install]
WantedBy=multi-user.target
It fails to startup (sudo systemctl start speedcomplainer.service) with this error:
speedcomplainer.service - Ethernet Speed Complainer
Loaded: loaded (/lib/systemd/system/speedcomplainer.service; enabled; vendor preset: enabled)
Active: failed (Result: start-limit) since Wed 2016-02-24 20:21:02 CST; 7s ago
Process: 25325 ExecStart=/usr/bin/speedcomplainer (code=exited, status=1/FAILURE)
Main PID: 25325 (code=exited, status=1/FAILURE)
I look at the log with journalctl -u speedcomplainer and :
Feb 24 20:21:02 haven systemd[1]: Started Ethernet Speed Complainer.
Feb 24 20:21:02 haven speedcomplainer[25325]: Traceback (most recent call last):
Feb 24 20:21:02 haven speedcomplainer[25325]: File "speedcomplainer.py", line 9, in <module>
Feb 24 20:21:02 haven speedcomplainer[25325]: import twitter
Feb 24 20:21:02 haven speedcomplainer[25325]: ImportError: No module named twitter
Feb 24 20:21:02 haven systemd[1]: speedcomplainer.service: Main process exited, code=exited, status=1/FAILURE
Feb 24 20:21:02 haven systemd[1]: speedcomplainer.service: Unit entered failed state.
Feb 24 20:21:02 haven systemd[1]: speedcomplainer.service: Failed with result 'exit-code'.
Feb 24 20:21:02 haven systemd[1]: speedcomplainer.service: Service hold-off time over, scheduling restart.
Feb 24 20:21:02 haven systemd[1]: Stopped Ethernet Speed Complainer
AHAHA!! An import error in the python script.
But wait - it works from everywhere else. Why am I getting an Import error only when it runs from systemd? (Answer - the module is installed locally. Next question:)
OK. After following the path that #jcomeau_ictx lead me down, it seems that pip installed to my local user directory. How do I install modules for root use?
OK. Thanks to jcomeau_ictx, I figured out the problem. pip installs locally, by default. This post discussed in detail how to install systemwide (TL;DR apt-get.). This installed for the root user. I didn't want to mess with a virtual env, and it's only one module with few dependencies.

Categories