2

This is my very first question, so forgive me if I am not correctly following the forum rules ;;))

I am looking to automate a python script for a webpage using GPIO pins that I can remotely enable through the webpage. The thing is that the script requires some sort of GUI to work, otherwise it doesn't start. I use HTTP.server library which is very handy and rather simple (I tried flask server as well but since I only need one page I prefer to stick with this) and the main element of the script is the BaseHTTPRequestHandler class

In my crontab configuration file, I have added the following line to execute the script on bootup (which happens frequently) @reboot python3 -u /home/pi/Desktop/webserver.py

When I look at crontab logs, here is what appears regarding my python file raspberrypi CRON[407]: (root) CMD (python3 -u /home/pi/Desktop/webserver.py ) I do not get any errors (or at least I don't see them)

But most importantly I know the file doesn't seem to execute It only works once I run it in a GUI window because it requires some output window to show the logs. As you can see in the extract below, the python script prints text for each HTTP request.

pi@raspberrypi:~ $ sudo python3 Desktop/webserver.py
Server Starts - 192.168.1.36:4590
195.68.33.114 - - [10/Feb/2023 15:54:44] "GET / HTTP/1.1" 200 -
195.68.33.114 - - [10/Feb/2023 15:54:45] "GET / HTTP/1.1" 200 -
195.68.33.114 - - [10/Feb/2023 15:54:46] "GET / HTTP/1.1" 200 -

Is there any way I could run this script successfully without GUI on crontab, and (ideally) dump the logs in a separate file so that I can still know what's going on?

2 Answers 2

1

I'm not a cron user, and to be fair some people seem to have problems with any and all conventional methods of starting a boot service, but really the most proper is systemd, the init system used by most contemporary GNU/Linux distros including RpiOS. That's what it is intended for, whereas cron really is not; it's a service in itself intended to run quick (or at finite time wise) tasks as opposed to persistent things that run indefinitely.

Systemd can appear too complicated due to the extent of its features. This case should not be too difficult, however. This is an appropriate service file:

[Unit]                                             
Description=Python HTTP server                     
Requires=local-fs.target                           
Requires=network-online.target                     
After=network-online.target                        
                                                   
[Service]                                          
Type=simple                                        
StandardInput=null                                 
StandardOutput=file:/var/log/pythonHTTP.log        
StandardError=inherit                              
ExecStart=/usr/bin/python3 -u /home/pi/Desktop/webserver.py 
                                                   
[Install]                                          
WantedBy=default.target   

The Requires and Wants are a bit paranoid. You do need the root filesystem mounted read/write, but if you are just starting a server -- which listens on a port but does not try to establish any connections -- then you don't really need the network online first.

All the directives are listed in man systemd.directives together with their corresponding man page, if you want to look these up. There are hundreds of systemd man pages.

Anyway, put that in /etc/systemd/system (you will need root privileges) with a .service suffix, eg. pythonHTTP.service, then sudo systemctl enable pythonHTTP.service. This will start it on boot.

You can also start it manually with sudo systemctl start pythonHTTP. This doesn't provide feedback, but you can get that immediately afterward with sudo systemctl status pythonHTTP (you can also do this at reboot). If it failed, that should be clear, hopefully along with enough details to figure out why.

9
  • Yay it worked ! However I just get an error with sudo systemd enable pythonHTTP.service. I get anExcess arguments. error. Is that normal ? Many thanks. All I need now is a way to start it automatically on bootup ;)
    – nilouth
    Commented Feb 11, 2023 at 18:02
  • Ack! That should have been systemctl, not systemd! Corrected.
    – goldilocks
    Commented Feb 11, 2023 at 19:09
  • thanks ! ;)))))
    – nilouth
    Commented Feb 11, 2023 at 19:33
  • The code fails to start on its own... Very weird févr. 11 20:34:05 raspberrypi systemd[1]: Started Python HTTP server. févr. 11 20:34:09 raspberrypi systemd[1]: pythonHTTP.service: Main process exited, code=exited, status=1/FAILURE févr. 11 20:34:09 raspberrypi systemd[1]: pythonHTTP.service: Failed with result 'exit-code'. févr. 11 20:34:09 raspberrypi systemd[1]: pythonHTTP.service: Consumed 1.120s CPU time.
    – nilouth
    Commented Feb 11, 2023 at 19:37
  • ok I think I solved the issue. I guess the program was starting before the IP of my raspberry pi was determined, so I justed added 10 seconds before the program starts and it worked !!
    – nilouth
    Commented Feb 11, 2023 at 19:43
2

If you don't want to do this by configuring python logging:

https://stackoverflow.com/q/6386698/1151724

You can use shell redirection, as cron executes via a shell (but there may be some caveats about the syntax):

@reboot python3 -u /home/pi/Desktop/webserver.py >> /path/to/logfile 2>&1

The 2>&1 at the end is important, as the python logger by default writes to the standard error stream; this redirects that to the same place as >> (which redirects standard output stream).

Thus a simplified version of this is:

@reboot python3 -u /home/pi/Desktop/webserver.py 2>> /path/to/logfile

This redirects only standard error. The first one is bit nicer in that it does deal with standard out, and so will, eg., capture print() statements (they will end up interleaved with the log stuff, which is what running a script at a terminal looks like).

If the script doesn't seem to run at all and you are not getting any feedback about why (I am not a cron user, so I don't know if it logs errors but you could check sudo grep cron /var/log/syslog and see if there is anything there), try wrapping it in a simple shell script:

#!/bin/bash

# Redirects all output.
exec &> /path/to/logfile
date

python3 -u /home/pi/Desktop/webserver.py

Call this runserver.sh or whatever you like and put that in the crontab instead. The logfile will be created (remove it first if it already exists) with at least the date and time like so: Sat 11 Feb 09:50:34 EST 2023 at the top.

You may also want to put more logging into the script, eg., a simple print('Begin') at the top of main. If execution fails, you can then trace the issue this way.

12
  • Thanks ! I tried with the >> /path/to/logfile 2>&1 and2>> /path/to/logfile But it still doesn't seem to work (no problem with crontab, but I can't access my webpage, and I know It doesn't work because I can launch another instance in a separate terminal, which would not be possible when another instance already uses my port) Do you have any advice to disable any output coming from the python script ? From my point of view logging the output is a second necessity, actually.... Very weirdly, the http requests aren't printed with the print() statement in my code so I can't figur
    – nilouth
    Commented Feb 10, 2023 at 16:54
  • Are you saying you think the script is not being run at all?
    – goldilocks
    Commented Feb 10, 2023 at 16:59
  • by the way here is the pythoin file if you want to have a look [link](github.com/Oscar-T24/random-stuff
    – nilouth
    Commented Feb 10, 2023 at 17:04
  • I think the script is not running at all, but crontab tells me it's actually running ! I think It has to do with the lack of GUI... It never happened to me before
    – nilouth
    Commented Feb 10, 2023 at 17:05
  • I get a 404 for the link.
    – goldilocks
    Commented Feb 10, 2023 at 17:14

Your Answer

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

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