4

I have a raspberry pi python3 program "monitor.py" that works from the terminal
But it fails to run when I start it from boot.

Check status:

pi@raspberrypi:~ $ systemctl status monitor.service

● monitor.service - Service to start monitor in terminal on desktop  
  Loaded: loaded (/etc/systemd/system/monitor.service; enabled; vendor preset: enabled)  
   Active: failed (Result: exit-code) since Tue 2019-01-01 14:56:31 MST; 55s ago
  Process: 624 ExecStart=/usr/bin/python3 /home/pi/monitor.py >> /home/pi/Desktop/monitor.log (code=exited, status=1/  
 Main PID: 624 (code=exited, status=1/FAILURE)  

Jan 01 14:56:30 raspberrypi systemd[1]: Started Service to start monitor in terminal on desktop.  
Jan 01 14:56:31 raspberrypi python3[624]: Traceback (most recent call last):  
Jan 01 14:56:31 raspberrypi python3[624]:   File "/home/pi/monitor.py", line 6, in <module>  
Jan 01 14:56:31 raspberrypi python3[624]:     **cf = open (cmdfile,"w")**  
Jan 01 14:56:31 raspberrypi python3[624]: PermissionError: [Errno 13]   **Permission denied: 'cmdfile.txt'**  
Jan 01 14:56:31 raspberrypi systemd[1]: monitor.service: Main process exited, code=exited, status=1/FAILURE  
Jan 01 14:56:31 raspberrypi systemd[1]: monitor.service: Unit entered failed state.  
Jan 01 14:56:31 raspberrypi systemd[1]: monitor.service: Failed with result 'exit-code'.

Check for permissions:

pi@raspberrypi:~ $ ls -l cmdfile.txt
-rw-rw-rw- 1 pi pi 1 Dec 31 21:09 cmdfile.txt
pi@raspberrypi:~ $ ls -l monitor.py
-rwxrw-rw- 1 pi pi 506 Jan  1 09:50 monitor.py
pi@raspberrypi:~ $ ls -l /lib/systemd/system/monitor.service
-rwxr--r-- 1 root root 224 Dec 30 13:09 /lib/systemd/system/monitor.service
pi@raspberrypi:~ $ ls -l /home/pi/Desktop/monitor.log
-rw-r--r-- 1 pi pi 0 Jan  1 10:29 /home/pi/Desktop/monitor.log

The program monitor.py:

#!/usr/bin/python3

import time

cmdfile = "cmdfile.txt"
cf = open(cmdfile,"w")
cmd = 1
cf.write(str(cmd))
cf.close
isRunning = cmd
cntr = 0
wait = 10

while isRunning == cmd:
    cntr += 1
    print("Hello World:", cntr)
    cf = open(cmdfile,"r")
    cmd = int(cf.read())
    cf.close
    if isRunning != cmd:
        print("check interrupt")
        if cmd == 0:
            import os
            os.system("sudo reboot -h now")
        else: # incremented
            exit()

    time.sleep(wait)

The systemctl monitor.service:

[Unit]
Description=Service to start monitor in terminal on desktop
Wants=graphical.target
After=graphical.target
After=multi-user.target

[Service]
User=pi
Type=idle
ExecStart=/usr/bin/python3 /home/pi/monitor.py &  

[Install]
WantedBy=graphical.target
WantedBy=multi-user.target

Enable the new service:

pi@raspberrypi:~ $ sudo chmod 744 /lib/systemd/system/monitor.service
pi@raspberrypi:~ $ sudo systemctl daemon-reload
pi@raspberrypi:~ $ sudo systemctl enable monitor.service

Test the program:

pi@raspberrypi:~ $ ./monitor.py  #note dot at start of the line
Hello World: 1
Hello World: 2
Hello World: 3

Restart:

pi@raspberrypi:~ $ sudo reboot

Check Status:

pi@raspberrypi:~ $ systemctl status monitor.service

Stop: (requires password)

pi@raspberrypi:~ $ systemctl stop monitor.service

Edit again with:

pi@raspberrypi:~ $ sudo systemctl --full edit monitor.service

Edit Note -- modified the above: in monitor.service I changed the following.
Was:

ExecStart=/usr/bin/python3 /home/pi/monitor.py >> /home/pi/Desktop/monitor.log  

Now:

ExecStart=/usr/bin/python3 /home/pi/monitor.py &

To remove the log (simplify) and add the & (to exit)
It still fails but there is one less thing to question.

3
  • This is NOT a Pi question, and has nothing to do with file permissions. I do not know what the program is supposed to do or whether it will work BUT every single file needs to have a FULL path. Startup programs which create files or attempt to output text are generally a bad idea.
    – Milliways
    Jan 2, 2019 at 7:25
  • 2
    @Milliways Why are services that create output files a bad idea? Logs seems a very acceptable and very common output file. Outputting text likewise provides logging capability to systemd which will return you the output on request.
    – tobyd
    Jan 2, 2019 at 13:37
  • 1
    A unit is working as a service in the background. So sending a program already running in the background to the background again with prefix & is a very bad idea. Don't do that. The program is then completely out of control from systemd. If you want the behavior of traditional UNIX daemons then you must use Type=forking in Section [Service]. See man systemd.service.
    – Ingo
    Jan 3, 2019 at 1:21

1 Answer 1

4

You'll need to add a working directory to your unit file as the Pi user won't have write access to put cmdfile.txt into the root of the volume (or whereever systemd roots itself).

in your Unit file add...

[Service]
WorkingDirectory=/home/pi

...and reload the daemon. You can change this to where you want but it must be somewhere pi can write to.

1
  • per @tobyd added under [Service] WorkingDirectory=/home/pi per @Ingo restored ExecStart=/usr/bin/python3 /home/pi/monitor.py >> /home/pi/Desktop/monitor.log Success!! Thank you. On testing reboot I set cmdfile.txt to 0 externally. The app read the file and Reboot worked. Now I am in an infinite reboot loop. I suspect the system postpones a write to the file. I need to force a write before continuing. Now I am researching systemctl disable monitor.service It looks like the Shift key will allow me to reload the operating system. Sometimes it is hard to recognize progress. Jan 3, 2019 at 17:54

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.