Build a Raspberry Pi Vehicle Interior Monitor – Running Code at Startup

Posted by Graham Smith on November 21, 2017No Comments (click here to comment)

In this blog series I'm documenting my maker journey as I build a Raspberry Pi-based vehicle interior monitor (PiVIM). Please refer to the previous posts in this series for the story so far:

Originally I'd assumed that the topic of this blog—running code at startup—was so straightforward that it wouldn't warrant a post of its own. However I ran in to a nasty gotcha, the fix for which might help somebody else, and I also learned a continuous delivery lesson (I'm slightly ashamed to say, given that much of what I blog about is continuous delivery) which is worth explaining.

When it comes to running code or programs at startup on Linux there are several ways to tackle the problem—see this useful Dexter Industries post which describes five different methods. I had no prior experience of this, and since I'd seen quite a few forum posts advising using rc.local and it was the first in the Dexter Industries list of five I started with that. The starting point is to edit the file:

and then add this command before the exit 0 line:

In case you were wondering, the long alphanumeric being passed in to my_pivim.py is the (obscured) access key for my InitialState streaming analytics account, and the ampersand at the end ‘forks the process' so the Raspberry Pi can continue booting. Anyway, quick reboot and sit back to watch my code spring in to life...

Or not since nothing happened. Check the syntax and try again—nothing. So I tried running the command from a prompt and ran in to this error:

So the requests module can't be found. Very weird since the shortened version of the syntax works absolutely fine from the command line in the PiVIM-py directory:

Next stop was to try without sudo, since everything in rc.local runs (apparently) as root anyway. The result of that was that the command didn't run in rc.local but did run from a command prompt. So, some sort of permissions thing, but was the problem limited to just the requests module? To cut a long story short I found out that it was just the requests module that was causing the problem, which led to installing requests again but ultimately no joy. And Google searches didn't turn up anything useful at that stage either.

I decided to abandon rc.local and try systemd instead based on the recommendation of the Dexter Industries post. My initial unit file (as /lib/systemd/system/pivim.service) looked like this:

With the permissions set on the file and the service enabled I rebooted...to nothing. Fortunately, I was able to see what the service was doing using this command:

This resulted in some useful, albeit frustrating output:

Back to the same old problem. However, this time a Google search with systemd as part of the query came up trumps with this StackOverflow question where a respondent had the same problem as me. The answer was simple: add a User=pi line beneath the [Service] section.

With this change PiVIM's control panel sprang in to life on startup—as I had expected it to several hours earlier:

Why the requests module alone caused this issue I didn't manage to find out and probably never will. On the plus side I now know how useful systemd is, not least because of the range of useful commands that work with it (see here and here for useful guides).

And so to the moral of this story, which is that if you don't practice continuous delivery—ie if you are not frequently pushing your code to ‘production'—you are likely to get bitten by problems that only surface towards the end of your development effort. This wasn't too much of an issue for me at home but in a professional setting not practicing some form of continuous delivery causes major headaches for developers all the time. Even if you don't develop professionally you might get caught out at a fun event such as a hackathon, so it's definitely a habit worth trying to adopt.

Cheers—Graham