Search code examples
python-3.xenvironment-variablessystemdpython-ossystemctl

Linux / Raspberry Pi OS - Systemd not working with python3 script using OS module that accesses enviroment variable


I'm trying to use systemd to run a python3 script, it was working fine, however I changed my python script to use the built in OS module as I wanted to retrieve an enviroment variable from the system to use in the python script as a variable.

The python script is as follows:

#/usr/bin/python

import sys, requests, json, time, os
import paho.mqtt.client as mqtt
from requests.auth import HTTPBasicAuth
from datetime import datetime

MQTT_DEVICE_ID = os.environ['DEVICE_ID']+"/DEFENCE"

The DEVICE_ID enviroment variable comes from one I set in /etc/enviroment:

export DEVICE_ID="TEST1"

user@computer:~ $ echo $DEVICE_ID
TEST1

After adding this change to my python script the systemd service that runs this script no longer starts, it will work for a brief period then it will keep failing and thren working again and failing:

computer@computer:~ $ sudo systemctl status mqtt.service
● mqtt_defense.service - Arms the mqtt.py script that will alert if the device is moved
     Loaded: loaded (/etc/systemd/system/mqtt.service; disabled; vendor preset: enabled)
     Active: activating (auto-restart) (Result: exit-code) since Thu 2022-08-11 08:57:37 BST; 1s ago
    Process: 2442 ExecStart=python3 /scripts/mqtt.py (code=exited, status=1/FAILURE)
   Main PID: 2442 (code=exited, status=1/FAILURE)
        CPU: 631ms
    
Aug 11 08:57:37 computer systemd[1]: mqtt.service: Main process exited, code=exited, status=1/FAILURE
Aug 11 08:57:37 computer systemd[1]: mqtt.service: Failed with result 'exit-code'.
user@computer:~ $ sudo systemctl status mqtt_defense.service
● mqtt.service - Arms the mqtt.py script that will alert if the device is moved
     Loaded: loaded (/etc/systemd/system/mqtt.service; disabled; vendor preset: enabled)
     Active: activating (auto-restart) (Result: exit-code) since Thu 2022-08-11 08:57:37 BST; 3s ago
    Process: 2442 ExecStart=python3 /scripts/mqtt.py (code=exited, status=1/FAILURE)
   Main PID: 2442 (code=exited, status=1/FAILURE)
        CPU: 631ms

Aug 11 08:57:37 computer systemd[1]: mqtt.service: Main process exited, code=exited, status=1/FAILURE
Aug 11 08:57:37 computer systemd[1]: mqtt.service: Failed with result 'exit-code'.
user@computer:~ $ sudo systemctl status mqtt.service
● mqtt.service - Arms the mqtt_defense.py script that will alert if the device is moved
     Loaded: loaded (/etc/systemd/system/mqtt.service; disabled; vendor preset: enabled)
     Active: active (running) since Thu 2022-08-11 08:57:59 BST; 304ms ago
   Main PID: 2475 (python3)
      Tasks: 1 (limit: 3720)
        CPU: 295ms
     CGroup: /system.slice/mqtt.service
             └─2475 python3 /scripts/mqtt.py

Aug 11 08:57:59 computer systemd[1]: Started Arms the mqtt.py script that will alert if the device is moved.
user@computer:~ $ sudo systemctl status mqtt.service
● mqtt.service - Arms the mqtt.py script that will alert if the device is moved
     Loaded: loaded (/etc/systemd/system/mqtt.service; disabled; vendor preset: enabled)
     Active: activating (auto-restart) (Result: exit-code) since Thu 2022-08-11 08:58:40 BST; 2s ago
    Process: 2551 ExecStart=python3 /scripts/mqtt.py (code=exited, status=1/FAILURE)
   Main PID: 2551 (code=exited, status=1/FAILURE)
        CPU: 633ms

After reading a few other questions on this issue such as this, I've tried altering my service to add the WorkingDirectory, User and Group as follows:

[Unit]
Description=Runs the mqtt.py script 
After=multi-user.target

[Service]
WorkingDirectory=/scripts/
User=user
Group=user
Type=simple
ExecStart=python3 /scripts/mqtt.py
Restart=always
RestartSec=5
TimeoutSec=60
RuntimeMaxSec=infinity

[Install]
WantedBy=multi-user.target

I've also tried changing the User and Group to root, still with no success. If I don't use the OS module in my python script the systemd service runs perfectly.

I have a feeling this is a specific problem with the python OS module or that I'm trying to access etc/enviroment in my python script, but I'm not sure what would be the issue.

Any help would be appreciated, thanks.


Solution

  • This has nothing to do with Python. Your problem is that systemd doesn't expose the env vars defined in /etc/environment by default. See, for example, https://unix.stackexchange.com/questions/473001/env-vars-in-etc-environment-not-globally-visible. As explained in the answer to that question /etc/environment is only loaded by PAM (pluggable authentication module) managed sessions such as interactive logins. AFAIK, systemd doesn't use PAM.