Close

Raspberry Pi - Bash - A hard job & a lazy man

A project log for Not Just Another Coffee Table

Custom coffee table with a DCC train track, automation, LEDs and a web interface

jack-flynnJack Flynn 10/03/2018 at 13:280 Comments

After detailing the code flow for the Raspberry Pi and getting some initial scripts working with Redis and my Teensy, I realised that I was having to launch 3 different objects manually in order to get everything working. I had to run Django via the manage.py to get the site up, then open another terminal and run Redis for passing data between my scripts and finally to get the Teensy communication working I had to run the "ArduinoEffectsManager" script. An added step was also that I had to launch my virtual environment before running my python scripts. 

While debugging this was really useful as I could track the printed outputs from my scripts but for a quick demo it wasn't ideal. There's a quote that goes around; "Whenever there is a hard job to be done I assign it to a lazy man; he is sure to find an easy way of doing it.". I decided to be lazy and find a nicer way to get everything running as eventually I would need everything running without my input anyway and it had me learn a bit more about running tasks on linux. 

For setting up Redis I followed this guide here. There were a couple of issues to begin with but I got it working and it's easy enough to follow so now Redis is running on boot of the Pi without any input from me.

For the rest of the code the main goal was to get a "launcher" script that I could call upon to get everything running the way I wanted. I've used a tiny bit of shell commands so I knew I could write a shell script to do this. I tested the following;

#!/bin/sh
python ArduinoEffectsManager.py

Which worked for launching the Arduino Effects Manager(AEM). However, this literally ran the script in my terminal and caused me to again see the debug outputs from the AEM. The script also stopped when I closed my terminal. I need to disassociated the call to my terminal to prevent the script from stopping when I close and I also needed to run it in the background to hide the debug output. It's a common enough issue and solved with nohup and the "&";

nohup ArduinoEffectsManager.py &

So now my python script is running in the background when I launch my shell script. The "print" debug calls from the script are stored in a separate file under "nohup.out" for the script. Except this didn't work for Django! This was because my shell script wasn't calling my python code from my virtual environment so Django was missing dependencies.

It turned out that to get my virtual environment working I needed to go a step above shell and create a full 'bash' script in order to support the "source" call. A little bit of jiggery-pokery and testing and my final script ended up like this;

#!/bin/bash
set -x #echo on
cd ~ #go to pi root
cd /share/djangoTrain #go to our shared development folder
source myvenv/bin/activate #activate the virtual environement
nohup python manage.py runserver 0:8080 & #run django in backround 
cd python_scripts # move to python scripts store
nohup python ArduinoEffectsManager.py & #run our manager script

 Now I can call my "launcher.sh" script via bash and I get the following output;

pi@rasppijack:/share/djangoTrain $ bash launcherFile.sh
+ cd /home/pi
+ cd /share/djangoTrain
+ source myvenv/bin/activate
++ deactivate nondestructive
++ '[' -n '' ']'
++ '[' -n '' ']'
++ '[' -n /bin/bash -o -n '' ']'
++ hash -r
++ '[' -n '' ']'
++ unset VIRTUAL_ENV
++ '[' '!' nondestructive = nondestructive ']'
++ VIRTUAL_ENV=/share/djangoTrain/myvenv
++ export VIRTUAL_ENV
++ _OLD_VIRTUAL_PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/local/games:/usr/games
++ PATH=/share/djangoTrain/myvenv/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/local/games:/usr/games
++ export PATH
++ '[' -n '' ']'
++ '[' -z '' ']'
++ _OLD_VIRTUAL_PS1=
++ '[' 'x(myvenv) ' '!=' x ']'
++ PS1='(myvenv) '
++ export PS1
++ '[' -n /bin/bash -o -n '' ']'
++ hash -r
+ cd python_scripts
+ nohup python manage.py runserver 0:8080
+ nohup python ArduinoEffectsManager.py
nohup: appending output to 'nohup.out'
nohup: appending output to 'nohup.out'

 Now my site is running and so is the AEM!

"Stop the presses!"

But how do I know they're running? And how do we stop the scripts if we want to change something? Well that's also easy enough with "ps agx". This command shows every process currently running on the Pi (equivalent to Windows Taskmanager). 

pi@rasppijack:/share/djangoTrain $ ps agx
(...Hidden stuff, its a big output)
11901 ?        I      0:00 [kworker/u8:0]
12183 ?        S      0:01 /usr/sbin/smbd
12215 ?        I      0:00 [kworker/1:0]
12426 pts/0    S      0:03 python manage.py runserver 0:8080
12427 pts/0    R      0:12 python ArduinoEffectsManager.py
12431 pts/0    Sl     0:04 /share/djangoTrain/myvenv/bin/python manage.py runserver 0:8080
12451 pts/0    R+     0:00 ps agx

We can now see the scripts are running and each has an associated PID which we can use to close the script. 

pi@rasppijack:/share/djangoTrain $sudo kill 12427

Through a "sudo kill" command we can close the script down and then it's ready for editing and re-running. 

A little bit of work for today but it'll save repeatedly opening terminals and running individual scripts. It's nice that we can easily access the scripts debug print outputs via the "nohup.out" files so even if something runs strange we can quickly check the file and see what happened. 

Discussions