1

Setup:
Raspberry Pi 2 Model B V1.1
Raspbian Jessie Version March 2016

Hi I am new in the RPI world, I managed to setup 2 DHT22 temperature sensors connected to GPIOs 22 and 23, 2 analog temperature sensors and 1 light sensor connected to a MCP3008 analog to digital converter via hardware SPI. I also managed to send the readings every 5 seconds to a mysql library. I also setup a LAMP server. To send the values to the internet, I make use of the dweepy library to use the www.dweet.io website to eventually create a dashboard in freeboard.io. I was able to accomplish all that. The python code is located at /home/pi/python_programs/sensors.py.

I want to run the code at startup, I was able to do that only after login as pi by doing this:

sudo nano /etc/profile

Scroll to the bottom and add the following line :

sudo python /home/pi/pythom_programs/sensors.py &

This only works after I SSH to the pi and then login as pi. I want the program to run without any intervention. I have already tried the @reboot in crontab -e, but it didn't work. I know that I have to go through systemd service setup since this is how the latest jessie runs its services (as far as I know). I have seen tutorials that deal with rc.local, but as far as I know, I MUST USE SYSTEMD IN THE LATEST JESSIE. I have tried several instructions online for systemd but I do not know how it works at all. Can somebody please help me.

@steverobillard Thank you for your response, I am also sorry I replied in the comment section. I followed your link and the python program worked partially. The program is supposed to read the sensors, store the values in a mysql database, then send them via internet to the dweet.io website, wait for 5 seconds and start from the beginning again). It reads the sensor, then saves the data in the mysql database, but it doesnt run the dweepy command dweepy.dweet_for('luxerel_rpi', binary,). This is the code for the luxerel.service file that I created:

[Unit]  
Description=Luxerel Sensors  
After=multi-user.target  

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

[Install]  
WantedBy=multi-user.target

When I test the service by entering sudo systemctl status -l luxerel.service y get the following output http://res.cloudinary.com/luxerel/image/upload/v1460048041/Capture_2_waeqqz.jpg

I think it is due to the network not being ready when systemd invokes the python script. I have seen the Wants and After commands included in the service file, but I do not know the right order, or in which sections to include them.

Please help me.

Thank you

@goldilocks Thank you for your help. I performed the following changes inside /home/pi/luxerel_programs:

$sudo nano startup.sh

Then entered this code:

*#!/bin/bash*


*exec &> /home/pi/myscript.log*  
*echo $(date)*  

*# Fork/exec*  
*(*  
    *exec /usr/bin/python /home/pi/luxerel_programs/luxmspv1.py*  
*) &*  

*exit 0*  

Then:

$sudo chmod 755 /home/pi/luxerel_programs/startup.sh  

$sudo nano /lib/systemd/system/luxerel.service  

I entered:

[Unit]  
Description=Luxerel Sensors  
Requires=local-fs.target  

[Service]  
Type=forking  
GuessMainPID=no  
StandardInput=null  
ExecStart=/home/pi/luxerel_programs/startup.sh  

[Install]  
WantedBy=default.target  

Then:

$sudo systemctl daemon-reload  

$sudo systemctl enable luxerel.service

$sudo reboot  

Once again it read everything but did not trigger the dweepy command at startup.

Please help!!!

Thank you!!

------------- UPDATE 04/08/2016 ---------------

@goldilocks, I thought it worked, but it didn't. I performed the following changes:

$ sudo nano /home/pi/luxerel_programs/startup.sh  

*#!/bin/bash*  




exec &> /home/pi/myscript.log  
echo $(date)  

*# Fork/exec*  
(  

*### Optional Code*  

        target=google.com  
        limit=100  

        count=0  
        while [ $count -lt $limit ]; do  
                count=$(($count+1))  
                ping -c 1 $target &> /dev/null  
                if [ $? -eq 0 ]; then  
                        echo "Online."  
                        break;  
                fi  
                echo "Ping $target failed..."  
                sleep 2  
        done  

        echo "$count pings."  

*### End Optional Code*

        exec /usr/bin/python /home/pi/luxerel_programs/luxmspv1.py  
) &  

exit 0  

Then I entered

$ sudo chmod 755 /home/pi/luxerel_programs/startup.sh  

$  sudo nano /lib/systemd/system/luxerel.service  

[Unit]  
Description=Luxerel Sensors  
Requires=local-fs.target  



[Service]  
Type=forking  
GuessMainPID=no  
StandardInput=null  
ExecStart=/home/pi/luxerel_programs/startup.sh  

[Install]  
WantedBy=default.target  

I also tried adding Requires=network-online.target but it didn't work. For some reason, I think it worked once, but it didn't work again.

Please help me!!

Thank you!!

6
  • Have you seen this raspberrypi-spy.co.uk/2015/10/… Apr 6, 2016 at 21:24
  • It is not that difficult to make systemd service which runs a script but it requires a bit of study, as it is different in concept. See wiki.ubuntu.com/SystemdForUpstartUsers. I find cron much easier. As you didn't post your cron we can't help. NOTE that the script (and everything it calls) NEEDS to be able run without logging in - no matter what method is used.
    – Milliways
    Apr 6, 2016 at 23:32
  • @steve Thank you for your link, I followed it and I got it to work partially. What I mean is that the python code gets the data from the sensors, saves it in the mysql database but when it comes to run the dweepy command: dweepy.dweet_for('luxerel_rpi', binary,) it doesn't do it. My service is called luxerel.service and this is its content: [Unit] Description=Luxerel Sensors After=multi-user.target [Service] Type=idle ExecStart=/usr/bin/python /home/pi/luxerel_programs/luxmspv1.py & > /home/pi/my$ [Install] WantedBy=multi-user.target
    – jmmb392
    Apr 7, 2016 at 16:27
  • @steve When I test the service: sudo systemctl status luxerel.service I get the following response:
    – jmmb392
    Apr 7, 2016 at 16:43
  • Please don't use the comments to add additional info - instead edit your question and add them there, Then you can ping the specific person to look at your edits. Apr 7, 2016 at 16:45

2 Answers 2

0

Systemd's primary documentation is in man pages, something you should like-it-or-not get used to reading. If reading them in a terminal is a little too old school for you, man -H should display them in your browser if $BROWSER is set (although I am not sure about this on Raspbian as I usually use it sans GUI, headless, and not all distros support this).

There's a stack of such man pages which apropos systemd will show you (and see man apropos for what that's about). There is a logic to their organization but you may have to read them a bit before it becomes clear. In this case we're interested in man systemd.unit and man systemd.service, which more-or-less correspond to documentation for the fields listed under those headings ([Unit] and [System]) from the service file. "More-or-less" meaning, not necessarily, some stuff is in man systemd.exec and elsewhere. Note that man pages in the terminal are easily searchable via /, because the normal viewer is a program called less, and that's a traditional "search key" in many traditional TUI apps (with which regular expressions can be used, in this case).

Anyway, I don't think making After= and WantedBy= the same is a very good idea. Generally your WantedBy= should be default.target, that way it is most likely to apply (although "default.target" may be "multi-user.target", it's also a target of its own).

I suggest you read man systemd.unit to understand the difference between After=, Requires=, and WantedBy=. You definitely need the last one, but the first two are optional.

In your case, I think you do need actual network connectivity for your script to work. This answer claims there is a systemd target for that, at least with some configurations.

A major problem I see is this:

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

First, type idle, described in the docs as a form of simple, is not necessarily "simple" in the sense of "simplest to use" (I think it's called that because it refers to something which is structurally "simple" in an init service context).

Second, doing bunches of shell redirection in the ExecStart may or may not be allowed/encouraged/described in various tutorials or examples but I think it is a bad idea. There are other aspects of the [Service] block intended to deal with this stuff, the only one you should bother with is:

StandardInput=null

Which in essence means this process does not expect or make use of any standard input.

There are corresponding ways to do redirection with StandardError and StandardOutput but I recommend against using them (all these are documented in man systemd.exec, not systemd.service), partially because they bring us back to the realm of the not-so-simple Type=simple service.

Instead, capsulize your thing in its own startup script. I'm going to include in this how I would check to wait for network connectivity; you can try this if the network-online.target mentioned later doesn't work.

#!/bin/bash
# Be sure that's 'bash' not just 'sh'.

exec &> /home/pi/myscript.log
echo $(date)

# Fork/exec
(

#### This starts the stuff you may not need.

    target=google.com
    limit=100

    count=0
    while [ $count -lt $limit ]; do
        count=$(($count+1))
        ping -c 1 $target &> /dev/null
        if [ $? -eq 0 ]; then
            echo "Online."
            break;
        fi
        echo "Ping $target failed..."
        sleep 2
    done

    echo "$count pings."

##### End of optional stuff.  

    exec /usr/bin/python /home/pi/luxerel_programs/luxmspv1.py
) &

exit 0

To explain the "optional stuff":

  • www.dweet.io doesn't respond to pings, but google.com is very reliable this way.

  • You may change the initial limit, and further down the sleep duration (seconds) to extend how long to wait for. Right now this totals 200 seconds before it gives up (it will proceed immediately when the ping succeeds).

Now the service file:

[Unit]
Description=Luxerel Sensors
Requires=local-fs.target
Requires=network-online.target

[Service]
Type=forking
GuessMainPID=no
StandardInput=null
ExecStart=/path/to/the/start-up.sh

[Intall]
WantedBy=default.target

There's a Requires=local-fs.target because almost anything useful (and certiainly this) first needs the root filesystem mounted properly.

The other Requires comes from the other answer about waiting for network connectivity. Try that, and if it doesn't work, remove that line from the service file and try the ping loop in the wrapper script instead. If you do do that, be sure to check the log file. There should be a lot of stuff in there one way or the other.

Note if there is some mySQL service involved, prequisite, and systemd controlled, you should look into that. I'm not a mySQL user so I don't know.

systemctl list-units | grep -i sql

Should give you a clue about this. OTOH, by the time the network is online that should be going anyway.

The [Service] part is primarily designed to make this something systemd will fire and forget, which is the real "simple" in the sense of "simplest to manage".

Disable your previous versions then try installing that one, systemctl enable whatever, and see what happens.

7
  • Thank you for your response, please review my update. Thank you!!
    – jmmb392
    Apr 7, 2016 at 23:04
  • I realized when I re-read your question and error that you probably do need internet connectivity for that to work. I've added some stuff about this starting with the 5th paragraph above, which links to another Q&A at our big sibling site Unix & Linux, and then makes a couple of suggestions including an adaptation to the wrapper script.
    – goldilocks
    Apr 7, 2016 at 23:46
  • Dear friend, I added the extra pinging code to the bash file, and it worked as I wanted it to work. I really appreciate all your help. Thank you very much!!!
    – jmmb392
    Apr 8, 2016 at 15:21
  • Hi, I am sorry to bother you again, I thought that I had made it work, but I didn't. Please review my update. Once again, thank you for your cooperation.
    – jmmb392
    Apr 8, 2016 at 23:05
  • If there is literally nothing in /home/pi/myscript.log after boot you've done something wrong with enabling the service. At the very least it should have the output from $(date) in it.
    – goldilocks
    Apr 8, 2016 at 23:23
0

In order to run script at startup, using crontab is fairly the best way.

Have you run crontab -e as superuser (with sudo)?

If not you must do so because only superuser can manage GPIO :

sudo crontab -e

If you did, why don't you try capturing what happens in an error log like so :

@reboot [command] > actions_log.txt

Also, does crontab work at all for you? You can do as follows to check :

@reboot touch test_file.txt

And see if the file is created or not.

3
  • Hi, thank you for your response, I think crontab is not working for me, I tried your test @reboot touch test_file.txt and the file was not created.
    – jmmb392
    Apr 7, 2016 at 13:46
  • Did you try getting errors in a log ?
    – Ramanewbie
    Apr 7, 2016 at 16:22
  • (@reboot [command] > actions_log.txt) If yes, what does the the log say ? Also, if not done yet you should restart your RPi and restart the crontab : sudo /etc/init.d/cron restart
    – Ramanewbie
    Apr 7, 2016 at 16:28

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.