3

I thought that running commands on raspberry pi on boot was the easiest thing in my project. But it seems that it is complex enough not to work.

I've searched a lot on the internet on a simple objective that I couldn't solve yet. All I want to do is to launch chromium normally (not in full-screen mode or any other setting). I also need to start node.js server on boot.

I've followed this website but that didn't help at all.

I kept on seeing gnome-scheduler that is a GUI application that is supposed to run commands on boot. Now this package is deprecated, but I found previous versions at launchpad that I downloaded but I know nothing about how and where to put the downloaded files in order to work.

In the convenience of what I am looking for, I made a python script that is supposed to open a URL in chromium. And the issue should be simplified if I just put the two commands :

  • Run Python (Open URL in Chromium)
  • Start listening on Node.js server

But after using all the methods that were stated at the above tutorial none seem to work. Maybe the problem is that when the raspberry pi is booting other services doesn't seem to load completely.

OS: Raspbian Buster

The method I am working on is SYSTEMD:

import webbrowser
import time

time.sleep(30) #To debug if latency is the problem
webbrowser.open('https://www.google.com')
print("Hey There Log File! I made it till here!")

But this python script doesn't run because when I check the log file it is empty neither anything is printed nor the browser opens why?

Edit1: Write a new Unit file sudo nano /lib/systemd/system/sample.service

Inserting code:

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

[Service]
Type=idle
ExecStart=/usr/bin/python3 /home/pi/sample.py

[Install]
WantedBy=multi-user.target

In order to store the script’s text output in a log file, you can change the ExecStart line to:

ExecStart=/usr/bin/python3 /home/pi/sample.py > /home/pi/sample.log 2>&1

The permission on the unit file needs to be set to 644 :

sudo chmod 644 /lib/systemd/system/sample.service

Now the unit file has been defined we can tell systemd to start it during the boot sequence :

sudo systemctl daemon-reload
sudo systemctl enable sample.service

Then reboot Raspberry Pi.

Edit2:

Thanks to @JayBuckel and his question: Issues when trying to open Chromium at a certain URL on boot. I have made some progress. All I had to do was to insert my command @chromium-browser https://www.google.com just before the @xscreensaver -no-splash line and Chromium starts at boot and directs to the relevant URL.

All I have to do now is to run node server.js command somewhere.

Edit3:

Currently, I am reading about how to Run node.js service with systemd?

Take a look at this for running a node server continously using pm2 https://raspberrypi.stackexchange.com/a/94850/90033

Ingo
  • 42,961
  • 20
  • 87
  • 207
Youssof
  • 135
  • 10

4 Answers4

3

If you're expecting a GUI browser to open, the DISPLAY environment variable may need to be explicitly set so that the browser the webbrowser module opens knows where to show itself. Otherwise it would likely not start at all and instead crash, not finding a valid GUI. For a systemd.service, you would do this by adding the line

Environment=DISPLAY=:0

to the [Service] section of the file before the ExecStart. You may instead need to specify the XAUTHORITY environment variable, as described here due to the service running as a different user. In which case the line to add would be

Environment=XAUTHORITY=/home/pi/.Xauthority

where 'pi' is the username the startup X instance runs as.

The reason you may not be seeing the printed log statement is a crash out of the script, the webbrowser has started a command line only browser, like links, and is waiting, or the GUI has not yet started when the python script finally gets to launching the browser.

If the sole purpose of the python script is to open a browser however, I would recommend directly starting the browser instead of relying on a Python script to do that. If you are concerned about the browser starting after node.js or the GUI, systemd service dependencies can be used to ensure it starts after those two using, e.g., Wants=mynodejs.service lines, see here for more details.

Fred
  • 4,592
  • 19
  • 29
3

In order to store the script’s text output in a log file, you can change the ExecStart line to: ExecStart=/usr/bin/python3 /home/pi/sample.py > /home/pi/sample.log 2>&1

This is wrong, although I notice there are a few Raspberry Pi oriented tutorials that claim it will work.

It will not work because > (and 2>&1) are POSIX shell operations, but you are not invoking this via a shell (as you would from the commandline). It's executed by systemd and all that stuff will be passed to the command (/usr/bin/python3) as arguments in addition to the script path, and those garbage arguments probably cause python to exit with an error.

You need to use these directives as explained in man systemd.exec:

StandardOutput=file:/home/pi/sample.log 
StandardError=file:/home/pi/sample.log 

You should test this with:

sudo systemctl start sample.service
sudo systemctl status sample.service

The last command is important because the first one alone may not provide you with all the relevant information. If you do this with sample.service as is (ie., don't fix the redirects), you will probably see the python error output.

Note that if you modify the service file after using systemctl enable you should run systemctl daemon-reload. However, you can test it directly without enabling it.

goldilocks
  • 60,325
  • 17
  • 117
  • 234
3

Just haven't a monitor by hand so I can't test it but here are some ideas how it could work with reference to this accepted answer How to make a service to run a python script which includes browser automation.

First of all we have a graphical output so the multi-user.target isn't enough. It is only for the text console. We have to use the graphical.target. Then I would not use a python script, so the unit could look like this:

[Unit]
Description=My Sample Service
Wants=graphical.target
After=graphical.target

[Service]
Environment=DISPLAY=:0
#User=pi
#WorkingDirectory=/home/pi
#ExecStartPre=/bin/sleep 30
ExecStart=/usr/bin/chromium-browser https://www.google.com
ExecStartPost=/bin/echo "Hey There Log File! I made it till here!"

[Install]
WantedBy=graphical.target

There are some commented lines for testing. I don't believe that you need a sleep. The output to stderr and stdout, here that echo, you will find in the journal:

rpi ~$ journalctl -b -e
Ingo
  • 42,961
  • 20
  • 87
  • 207
2

I had an issue like that with one of my Python projects, where I needed a Bash script with the steps to run my program to run not only after the Raspberry Pi boots, but also after the GUI loads. What worked for me was following the instructions in one of the posts in the "How to launch programs on LXDE startup" topic in the raspberypi.org forums, depending on the version of Raspbian doing

  • For Raspbian Wheezy with the LXDE GUI desktop: sudo nano /etc/xdg/lxsession/LXDE-pi/autostart
  • For Raspbian Jessie or Raspbian Stretch, with the Pixel GUI desktop: sudo nano /home/pi/.config/lxsession/LXDE-pi/autostart

to edit the autostart file, adding the line

@/home/pi/the_name_of_my_script

(because I had put my script in /home/pi :-)) to the end of the file, and saving it.