It's time to share your awesome Raspberry Pi project with the world! A more polished way is to create an installer script - an executable file that handles installing packages and tweaking settings for the user. This is what we'll be working on in this tutorial.
If you've ever tried to set up someone else's project on your own Raspberry Pi, what you will often find is that the set up process is this long list of commands that install packages and configure certain settings and this kind of approach to sharing your project can be a little intimidating for beginners and it's especially dull to have to sit there and babysit a Raspberry Pi while it is downloading and installing large packages because that can be quite slow. This motivates us for if we ever release our own project, to create an installer script that automates as much of the procedure as possible and that's something we're going to explore today. So recently I published a project which was a Raspberry Pi GIF camera that could tweet GIFs as they were taken and it was for that project that I decided to write an installer script and in this video, we're going to recreate that script and go through the workflow of how that was created. Now I'm no scripting expert so if you notice any scripting faux pas that I might have committed during the process, definitely let me know in the comment section or in the forums. Let's get started.
So this is tweeting GIF camera project relies on a few packages so our installer script has to install some packages, that should be a p, and those packages are the Pi Camera because of course, this is a camera that we're making. It needed to install a package called graphics magic, that is spelt with a CK, I haven't spelt it out for you, we'll look at that in the script and it needed to install pip. So Pi camera drives the camera, graphics magic is what creates our GIF from still images and Pip is a Python package manager because we also need to download a special Python package called Twython, and that is a package that allows us to create tweets using a Python script. Aside from installing those packages we also need to modify a specific file and that is the config file. So the config file is where we can configure the basic operation of our raspberry pi and the interfaces that are available so of course if we're going to use the camera interface we're going to have to enable it somehow by modifying this file. Now over on the raspberry pi say on the desktop, you would often do that action by going to preferences, going to Raspberry Pi configuration, or just minimize this Explorer going to the configuration going to the interfaces tab and then selecting to enable the camera from these radio buttons in the interfaces. Otherwise, you might do it through the terminal, where you would execute
and then you would navigate down to interfacing which is option 5 and then you would enable the camera from this menu. So what both of these options are doing, behind the scenes, is modifying this special config file. So that's how I would do it if we were actually interacting with the PI but for our script to enable the camera interface, we're going to have to modify this config file to enable camera. Ok, let's get started.
So back over on the Pi I'm just going to exit out of this raspi-config and I might as well close that terminal now before you proceed I'm going to assume that you've followed my "writing your first install script" because we're using a lot of the information from that before we proceed here. So the config file that we have to modify it in a special location but actually I'm getting ahead of myself let's just create an edit script so in my home hi directory I'm going to I create a new and empty file and I'll just call this script SH for a shell script. Okay there's our empty script and if I open it it is indeed empty, I'll just increase the font size, to make that a bit friendlier, is 26 too much well that's probably okay. All right so the first things first we have several packages that we want to install and that's pretty easy, we'll just include a note to ourselves install packages okay so I guess the first thing we need to do our script is putting that hash bang line, that hash exclamation point in and I'm going to use SH for this for this particular script so we need to install the packages and it's always good practice every time we install packages to run apt-get update and apt-get upgrade so I'll run those now I won't use sudo because I'm going to assume that this entire script has been run with the sudo permission so the run apt-get update and apt-get upgrade, Y, so that's going to just update our Raspberry Pi and make sure that all the packages are up-to-date before proceeding and then we need to actually install our packages so rather than have a big long line of apt-get install and then all of the packages I'm going to I'm going to maybe make it a little bit nicer look at and create as variables so I'm going to create a variable called packages and this is what we're going to set to the string as packages that we want to install so we need Pi camera, graphics magic, and Pip and the names for those are Python-pi camera graphics magick and pip is python-pip so we never have a variable called packages which has all the packages we want to install through APT, so we can then execute apt-get install and we're going to call our variable and then I'm just going to put in the - y option so that the user doesn't have to interact with the script, that's just going to say yes I do want to install all these packages I do want to use up that amount of disk space etc.
Okay what's next we needed to use pip to install python, that's right we need we needed to use click to install Twython, the Twitter package so I can do that with the command, pip install twython, and that is the easy part of our script knocked over so that's installing all the packages and all the dependencies that we need. Now if we were to run this script as it is, we would have to wait around for the update, the upgrade, and all the installs, and that would take will take quite a while to be honest so because I know that this is a good piece of code I'm just going to comment it out for the remainder of this video, so we can very quickly execute the script to test how it's going, so I'm just going to comment out each line, in turn, to save us the hassle. Now for the interesting part this is where we need to enable the camera interface and this is where things get a little bit trickier so the raspi-config interface is accessing a special file and that file is in root/boot/ and it's the config.txt file. What I'm going to do just to sandbox this so we don't break anything important while they're just having a muck around, I'll copy this file into my home directory so now I've got a copy of the config.txt file in my home directory, and while it's there I might as well create a variable in my script called config and set that equal to /home/pi/config.txt so now when we deploy our script properly all we have to do is change this variable to the true location of the config file for now, we're just sandboxing the whole thing just to play it safe so let's take a look at the config file to see what we're dealing with and I'll show you what we need to change. Here's our config file I'll minimize everything else and do the usual font business okay it's a pretty intimidating looking file is definitely quite a lot going on, you'll notice that most of its commented out, now what we're interested in this file are two things two lines, down the bottom, because I'm running NOOBs or my first installation was with NOOBs, this is automatically generated some settings for me you might see this when you might not it doesn't really matter because we'll cover all the cases.
So this NOOBs auto-generated settings area there are two lines that I'm interested in start_X=1 and GPUMan=128 so these are the two things that I absolutely need for the camera to work. Start_x=1, is I believe just enabling the camera interface so one is enabled and zero is disabled and for the camera to work properly we need to have 128 megabytes allocated to the GPU memory, so those are the two conditions that need to be met, now here's the thing here's the problem definition, we could have a situation where those two lines are present but with the wrong value so they could have start x equals zero or GPM M equals 64 we could have one missing or we could have both missing so we need to cover these different combinations that we're going to come across. I'll undo that for now and just to start with I'll set these to some incorrect values and we'll try to have our script correct them for us, so I'll set Start_x=0 and GPU mem=32 is it good a number as any and I'll save my config file. Now what we need to do in our script is somehow search this file to see if a line containing startX exists, if it exists then we want to make sure it's set to the right value, and if it doesn't exist that's fine we just want to create that line with the right value.
Let's first look for me to start X parameter using a command called grep, I'm not really sure how people say it so I'll call it Grep. Now grep is the program that searches within a file for a specific piece of text or a match and we can use, whether it finds a match or not, to control the behaviour of our program so let's let's start with the condition does this line exist at all. So we can say if a line containing that startx exists and we're just going to make a simple if statement, so it's going to look something like if and then and else, so we'll have some if condition, do something if it's true, and do something else, is its false. Now the command Grep that I'm going to use for this instance it's going to look something like this so we need to execute Grep and what we're looking for is a fixed string so start_ X that's the fixed string that we're searching for in the file so I can say I can pass it the option - capital F which means fixed and I also want to run this in quiet mode which will just suppress any output because this is the installer script and we don't want it to be throwing unnecessary information to the user, so we're just going to add a 'q' there for quite mode. Now the string that we're looking for is start_X and we're looking for it in the config file so let's just test that this that this works properly so I'm just going to tab in and just echo startX exists and in the else condition I'll echo startx not found, and then, of course, I have to close the statement with a Phi. We can pretty much run this now just to see if it works as expected for this IF statement remember I've commented out all the all the slow package installation so the only part of the trip that actually runs is this if statement, and in fact yep config is defined, that's fine so I can save this and I'll very quickly set it to an executable. So I'll just execute chmod view +X script.sh and you can see script.sh is now executable so I'm going to run this script just to see if it works so I can say script.sh and the feedback that we get it startx exists that's great because of course, we do have an entry in our file for startx=0. Now I'm going to delete it and we'll make sure that everything is working as it should there, remember this is the copy that I have in my home directory don't do this to the one that's in the boot, for instance, I'll just rerun the script and startX is not found. So we can definitely tell if an entry for startx exists at least once and that's good. So since we can tell if the line exists or not that's the functionality we have so far, let's work on the else condition when the line is not found, cause that's really easy. So in our script where we have the else startx not found we can very easily append the text that we want to the file append means just add to the bottom and we did that with the following commands so we can run the echo command and we can insert the text that we want which is start underscore X and then we pass that into the file config, so now if I save my script and remember I've deleted the line from config, so I'll just close that just remember the last line was GPUmem=32 and there was a space between it and the above parameter I'll just close that and run the script now start X was not found that is okay because the search for startX was, or that echo command was above that, append command, but now if we scroll right down to the bottom you can see we've got start X inserted under GPUmem and in fact I forgot to actually set the parameter of what I wanted it to, so I'll set startx equal to 1 and that is going to append the file with startx equal to 1. That mistake though, that could be a bit useful now for the next part where startx does exist, but we want to make sure that it's set to the correct value. So what we can do from here is use the string edit command which is known as sed so sed essentially takes a stream of data like when you're looking through a file and it modifies the contents of that string edit. So what we can do with stream edit is the search for pieces of text and replace them with exact substitutions, or you can replace whole lines so that's going to be really useful for us. The syntax that I'm going to use here is sed with the option I that means that we are modifying a file in place we want to just modify it where it is and then essentially save it I guess, so, we need to modify the file in place and then what comes next is an intimidating piece of syntax, I guess is it's filled with some funny looking syntax that we'll get over it so we're running sed with the substitute command because we're substituting some text and we're looking for, then I put in this forward slash which is like a delimiter, the next part means that we're looking for start_x=0 and I want to replace an exact match with start x equals zero to start underscore x equals one so we've got substitute commands look for this and replace with this and we want to do that of course in config.
Now as this line stands it won't work with my with my config file the way it is because I only have to start X I haven't got it set equal to anything which means that this file was actually kind of broken, so I'm just going to set it equal to zero and resave it, but I think that's all we need to do to look for this piece of text and then replace it or substitute it with an exact fit for startX=1. So if I now save this file and we re-execute the script, I have an unterminated s command, I forgot to include the last delimiter and I think that's going to throw another error. All right that was fine so I can close my config text, reopen it and we can see that now startX has been set equal to one, just just to push that point again I'll remove startX from the bottom line I'll put it back in where it was originally but with a zero, save the file, close config, run the script, startX exists, but we're making sure it exists with the right value. Open up config, scroll down and now startX equal to one so we've successfully flipped the contents of that line to what we want to be, now the next one is a little bit, different we want GPUmem to be set to 128 so the problem here is we've got a line that has not just two possible answers, it's not 0 or 1 it could be 12 it could be 8, 32, 128, which also means that it varies in length which means the substitute commands, it's not going to work every single time I don't think. So what I'm instead going to do for this next part is just look for a line containing GPUmem and regardless of what the value is set to I'm just going to erase it and set it to 128, so that means that is there already is a line that has GPUmem set to 128 doesn't matter I'm just going to erase it and set it to 128 not, probably not the most elegant way to do this but it will function for now I suppose, like I said I'm no veteran at this either.
So let's just take our script and what I'm about to do is this quite a dangerous thing really, copy/paste programming, it means that you have to be very careful with what you paste you want to make sure that you carefully inspect it as if you were essentially writing it out again. So if a line containing GPUmem exists, replace the whole line, okay that means that I'm looking for I'm Grepping for a line called GPUmem, remember this is looking to see if it even exists and we'll start off with the else condition first. So GPUmem not found and we need to append the file with GPUmem=128, okay that's fine so now we come back to our our condition where if it does exist and we can't just change these arguments or these bits of syntax to GPUmem and just and just have it work for us we need to replace the whole line so we're going to say, GPUmem and exists and this time with sed, we're going to edit the file in place that's okay but we're not going to use the substitute command for sed, that's not going to work to for us here because the line is varying in length and we're changing the whole line anyway so we're looking for a line containing GPUmem this is an important distinction before we were looking for startX is equal to something but here now we're just looking for GPUmem we don't care what comes after it and we're going to put in next GPU_mem equals 128 now we're not quite done between this delimiter and the next piece of syntax I'm going to include a sed command which is the change command, that changes a whole line so I'm going to put in a C and a backslash and what this is going to do for us is it's going to replace the line containing GPUmem with a new line containing GPUmem equals 128, like I said it's brute force, regardless of what it's set to. So I think that is more or less a complete script I'm going to save that and let's look at our config text where it is at the moment. We have start X equal 1 and we have GPU mem equal to 32 okay so 1 and 32, I'll close that config text, I'll open up my shell and I'll run the scripts so both of those lines exist that's okay, open up config text once again, scroll to the bottom and there's just a problem I've accidentally left a bit of a hangnail on that, so we don't need this last delimiter here, it's the danger of copy/paste programming, so I can save that. As we can see once I delete that slash, this slash would go away, so I can delete that let's now put out our installer script through its paces, I'm going to start off by deleting both lines, saving closing, running, both lines not found, open the text file and down the bottom there they are fantastic.
Now I'm going to set that to zero and set this to, this could be anything right this could be like hello world, and the script should still work so I can close that, run the script, open it again, scroll down and it's fixed it up fantastic. Okay so that it just about leaves us with a working Installer script I can close my shell, close my dummy config file, so now to finish commissioning the script, all we have to do is uncomment all the lines that we commented out just for the commissioning process, and of course we have to make sure we're editing the right file, remember I was editing just this copy in my home directory so I can delete that but I actually want to be editing the one that's in /boot/config.txt fantastic so that should be a complete install of scripts that's ready to get your Pi set up to run the GIF camera project. If you have any comments on how this installer script can be improved, and I'm almost certain that there are plenty of improvements that can be made to make it more elegant and more general-purpose absolutely let us know in the forums or the comments below and I'll include some links to these grep and sed commands because while you may not have seen them before they're very, very powerful tools and they definitely worth getting a little bit of experience with I'll catch you next time.