Search code examples
pythonraspberry-pisystemddebian-stretch

Otherwise ok running code won't run under systemd


Another newbie question from my side:) I tried to look it up but I couldn't find anything that makes sense in this case. I have this code which is working fine under normal circumstances.

import automationhat
import bluetooth
import time
import sys
import telegram

bot = telegram.Bot(token='56915444444:AAEzP5jy-pMD3ZME0twxY5bXkxxxxxxxxxxxxxxxxxxd_U')


# Import Adafruit IO MQTT client.
from Adafruit_IO import MQTTClient


ADAFRUIT_IO_KEY      = '73c755488accccccc361a506f700000002ba'
ADAFRUIT_IO_USERNAME = 'flxxxxxxxx'


def connected(client):
    print('Connected to Adafruit IO!  Listening for LockReg changes...')
    # Subscribe to changes on a feed named LockReg.
    client.subscribe('LockReg')

def disconnected(client):
    print('Disconnected from Adafruit IO!')
    sys.exit(1)

def message(client, feed_id, payload, retain):
    print('Feed {0} received new value: {1}'.format(feed_id, payload))

client = MQTTClient(ADAFRUIT_IO_USERNAME, ADAFRUIT_IO_KEY)

# Setup the callback functions defined above.
client.on_connect    = connected
client.on_disconnect = disconnected
client.on_message    = message

PHONES = ['B0:xx:2D:x0:C9:xx', 'xx:8D:08:xx:C3:7C', 'xx:AB:37:EA:93:xx']

while True:

        print "Checking " + time.strftime("%a, %d %b %Y %H:%M:%S", time.gmtime())

        for device in PHONES:
                result = bluetooth.lookup_name(device, timeout=5)
                if (result != None):
                    # Connect to the Adafruit IO server.
            client.connect()
            print('Door unlocked. Nearby: %s (%s)' % (result, device))
                        client.publish('lock.reg', result)
                        automationhat.relay.one.on()
                        time.sleep(2)
                        automationhat.relay.one.off()
            bot.sendMessage(-26934xxxxx, result)
                        time.sleep(180)
                else:
                        print "User out of range"
                        print('Door locked: No Bluetooth device detected. ' )
        time.sleep(10)

My systemd lock.service file looks like this:

[Unit]
 Description=My Lock  Service
 After=multi-user.target

 [Service]
 Type=idle
 ExecStart=/usr/bin/python /home/pi/lockreg.py > /home/pi/lock.log 2>&1

 [Install]
 WantedBy=multi-user.target

But if executed from systemd on initial boot i get the following error message:

pi@raspberrypi:~ $ systemctl status lock.service
● lock.service - My Lock  Service
   Loaded: loaded (/lib/systemd/system/lock.service; enabled; vendor preset: enabled)
   Active: failed (Result: exit-code) since Sat 2018-06-16 18:33:32 CEST; 29min ago
  Process: 492 ExecStart=/usr/bin/python /home/pi/lockreg.py > /home/pi/lock.log 2>&1 (
 Main PID: 492 (code=exited, status=1/FAILURE)

Jun 16 18:33:29 raspberrypi systemd[1]: Started My Lock  Service.
Jun 16 18:33:32 raspberrypi python[492]: Traceback (most recent call last):
Jun 16 18:33:32 raspberrypi python[492]:   File "/home/pi/lockreg.py", line 11, in <mod
Jun 16 18:33:32 raspberrypi python[492]:     import telegram
Jun 16 18:33:32 raspberrypi python[492]: ImportError: No module named telegram
Jun 16 18:33:32 raspberrypi systemd[1]: lock.service: Main process exited, code=exited,
Jun 16 18:33:32 raspberrypi systemd[1]: lock.service: Unit entered failed state.
Jun 16 18:33:32 raspberrypi systemd[1]: lock.service: Failed with result 'exit-code'.

Somehow the Telegram module is not accessible when executed from systemd. Why?

thanks for some hints P.


Solution

  • There are a couple of possible things that could be wrong.

    It could be that telegram is only installed for the user pi instead of globally for all users. Check /home/pi/.local/ to see if you can find telegram there.

    If not, you would expect the module to be installed in your system-wide site-packages directory. Use the following to find that:

    > python
    Python 2.7.15 (default, May 11 2018, 15:54:10) 
    Type "help", "copyright", "credits" or "license" for more information.
    >>> import sys
    >>> [p for p in sys.path if p.endswith('site-packages')]
    ['/usr/local/lib/python2.7/site-packages']
    >>>
    

    (It will probably be a different directory foy you, since my python lives in /usr/local/bin.)

    Then check that telegram is installed as a file or sub-directory in the site-packages directory.

    It could also be a permissions issue. Systemd is running your program as a certain user id. Check that the site-packages directory and the telegram subdirectory are readable by that specific user.

    Edit: Systemd can run in two modes; system and user. Only the latter runs as a specific user. I would guess that the system mode runs as root. From the location of your lock.service file, I gather you are using systemd in system mode. According to your comments, telegram is only installed for the user pi. So python running as root should not see it, which is exactly what you experience.

    So basically you have two choices:

    • Install telegram for all users. (Run the install as root.)
    • Run a user-mode systemd as the user pi.