Chapter 4. Exploring GNU/Linux Recipes Using Bash, Autotools, Debugger, and systemd
Here is what we've got in store as recipes in this chapter:
- The basic shell script
- Epoch Time shell script
- Compile and install
- Compile and install Git from source
- Debugging
- Debug a simple C-code application from the command line using GDB
- Debug an application remotely from Eclipse and GDB server
- systemd services
- Basic commands for systemd services
- Optimize boot time
- Create a systemd service to run at boot time
Introduction
In our last chapter, we jumped right into how to make our hardware dance or at least blink for us. This time, you will learn more about how to bend the software to your will.
We'll build on some foundational principles first and then head towards greater complexity of scripts, including how to compile an open source software package, install it on your system, and troubleshoot it when things go out of whack. Lastly, we'll examine some core, system-level software called systemd
, a framework that has become an essential ingredient in modern Linux distributions.
The basic shell script
Shell scripts
A shell script has a myriad of purposes on a Linux box. You can have them run at bootup so that they initiate commands or processes without you having to manually start them. They can be used to run a sequence of events. They can manipulate files, execute a program, print text, and walk your dog. Well, the last part is true if your dog is a robot. However, we're getting ahead of ourselves.
It's time for our friend Major Tom. We've missed him, but let's bring him back to earth for a moment with a very simple shell script.
How to do it...
Perform the following steps:
- Create a new directory as follows:
$ mkdir bin
- Then, let's move to the new directory using the
cd
command:$ cd bin
- Now, create a new file that will become our shell script, as shown in the following code:
~/bin$ sudo nano major_tom_bash_script
- At the beginning of the file, it's a requirement to tell the shell the kind of script that we'll run so that it can interpret the code accordingly. It could have been another recipe using Python, but in this case, we've got a bash script:
#!/bin/bash
- Next, it's a good practice to add a comment as follows:
# Major Tom bash script
- On the next line of the file, enter the
echo
string command, which outputs whatever you input to the screen:echo "Commencing countdown, engines on."
This is how the code looks:
#!/bin/bash # Major Tom bash script echo "Commencing countdown, engines on."
- Now, save and close the file.
- Then, from the terminal, you want to run a command that will give the shell the ability and permission to actually execute the script, as shown in the following code:
~/bin$ sudo chmod 755 major_tom_bash_script
Adding the
755
option instructs the script to allow read and execute access to everyone and write access to the file owner (you) as well. Refer to Chapter 1, Setting Up for the First Time, for our review of thechmod
command. - Finally, it's time for the magic (
.
). This tells bash to run the script, and (/
) tells bash where the file is located, as shown in the following code:~bin$ ./major_tom_bash_script
- This is how your output should look:
debian@beaglebone:~bin$ ./major_tom_bash_script Commencing countdown, engines on.
This is a very small blast off, but still a beginning.
How to do it...
Perform the following steps:
- Create a new directory as follows:
$ mkdir bin
- Then, let's move to the new directory using the
cd
command:$ cd bin
- Now, create a new file that will become our shell script, as shown in the following code:
~/bin$ sudo nano major_tom_bash_script
- At the beginning of the file, it's a requirement to tell the shell the kind of script that we'll run so that it can interpret the code accordingly. It could have been another recipe using Python, but in this case, we've got a bash script:
#!/bin/bash
- Next, it's a good practice to add a comment as follows:
# Major Tom bash script
- On the next line of the file, enter the
echo
string command, which outputs whatever you input to the screen:echo "Commencing countdown, engines on."
This is how the code looks:
#!/bin/bash # Major Tom bash script echo "Commencing countdown, engines on."
- Now, save and close the file.
- Then, from the terminal, you want to run a command that will give the shell the ability and permission to actually execute the script, as shown in the following code:
~/bin$ sudo chmod 755 major_tom_bash_script
Adding the
755
option instructs the script to allow read and execute access to everyone and write access to the file owner (you) as well. Refer to Chapter 1, Setting Up for the First Time, for our review of thechmod
command. - Finally, it's time for the magic (
.
). This tells bash to run the script, and (/
) tells bash where the file is located, as shown in the following code:~bin$ ./major_tom_bash_script
- This is how your output should look:
debian@beaglebone:~bin$ ./major_tom_bash_script Commencing countdown, engines on.
This is a very small blast off, but still a beginning.
Epoch Time shell script
Shell scripts
A shell script has a myriad of purposes on a Linux box. You can have them run at bootup so that they initiate commands or processes without you having to manually start them. They can be used to run a sequence of events. They can manipulate files, execute a program, print text, and walk your dog. Well, the last part is true if your dog is a robot. However, we're getting ahead of ourselves.
Epoch time, more commonly known as UNIX time (also POSIX time), is widely used in Linux (UNIX) systems as a way to describe instants in time. Specifically, it measures the number of seconds that have elapsed since January 1, 1970, and is used as a timestamp reference point.
With this shell script, we can quickly compare the Epoch time on our machine with the UTC that we are more accustomed to using.
How to do it...
Perform the following steps:
Unix time can be checked on most Unix systems by typing date +%s
on the command line. Perform the following steps:
- First, create the following script in
nano
:$ sudo nano epoch-time.sh
- Then, paste the following code in the new window:
# Epoch time in milliseconds # CTRL-C TO STOP # WRITTEN BY CHARLES HAMILTON # Simple script for showing the epoch time at 10-second intervals on a BeagleBone Black running Debian #!/bin/bash # Resets the RTC from the system clock sudo hwclock --systohc sudo hwclock --show # Runs command for determining epoch time for (( ; ; )) do echo -n "Since Epoch [in milliseconds]: " # OPTION 1 command. Comment out if running OPTION 2. echo $(($(date +%s%N)/1000000)) ## OPTION 2 command. Uncomment to run this version and comment out OPTION 1. # cat /sys/class/rtc/rtc0/since_epoch | sed 's/...$//' sleep 10 done
Note
If you run into problems while copying and pasting the code, download the script available at https://github.com/HudsonWerks/bash-script-samples/blob/master/epoch-time.sh.
- Now, run the following script:
$ sudo bash epoch.sh
- Your screen output should look similar to this:
Tue Oct 27 14:13:53 2015 -0.062322 seconds Since Epoch [in milliseconds]: 1445969632617 Since Epoch [in milliseconds]: 1445969642630
The script determines the Epoch time in milliseconds relative to the UTC time.
- Stop the script by pressing
Ctrl
+C
.
There's more...
For some, all you can eat is buffets with shell scripts on the menu:
How to do it...
Perform the following steps:
Unix time can be checked on most Unix systems by typing date +%s
on the command line. Perform the following steps:
- First, create the following script in
nano
:$ sudo nano epoch-time.sh
- Then, paste the following code in the new window:
# Epoch time in milliseconds # CTRL-C TO STOP # WRITTEN BY CHARLES HAMILTON # Simple script for showing the epoch time at 10-second intervals on a BeagleBone Black running Debian #!/bin/bash # Resets the RTC from the system clock sudo hwclock --systohc sudo hwclock --show # Runs command for determining epoch time for (( ; ; )) do echo -n "Since Epoch [in milliseconds]: " # OPTION 1 command. Comment out if running OPTION 2. echo $(($(date +%s%N)/1000000)) ## OPTION 2 command. Uncomment to run this version and comment out OPTION 1. # cat /sys/class/rtc/rtc0/since_epoch | sed 's/...$//' sleep 10 done
Note
If you run into problems while copying and pasting the code, download the script available at https://github.com/HudsonWerks/bash-script-samples/blob/master/epoch-time.sh.
- Now, run the following script:
$ sudo bash epoch.sh
- Your screen output should look similar to this:
Tue Oct 27 14:13:53 2015 -0.062322 seconds Since Epoch [in milliseconds]: 1445969632617 Since Epoch [in milliseconds]: 1445969642630
The script determines the Epoch time in milliseconds relative to the UTC time.
- Stop the script by pressing
Ctrl
+C
.
There's more...
For some, all you can eat is buffets with shell scripts on the menu:
There's more...
For some, all you can eat is buffets with shell scripts on the menu:
Compile and install
In Chapter 1, Setting Up for the First Time, you learned the magical apt-get install
routine to get a package that you want on your BeagleBone Black. However, you've already encountered situations where you wanted a package (typically abbreviated as pkg) and the repository came up with nada: E: Unable to locate package xyz
. This often implies that there is no precompiled binary for you to install, which means that we now have to put on our big girl and big boy boots and compile from source files.
Building software from original source files is one of the prerequisites when you work with SOCs, such as BeagleBone Black. This is true in part because the BBB is a Linux environment. Many software applications have to be compiled in order to use them. However, it's also a fact that you will often want a version of a tool that doesn't come with a packaged binary to suit your use case or the prototype that you'll build. Native packages (in our case, the armh
packages) are almost always a better fit than prebuilt binaries if you have the time and fortitude to build them.
Therefore, mastering, creating, and building from source files gives you tremendous power over how you customize and optimize the software that you use on the board.
Autotools, aka the GNU build system, is a toolset to build native packages. The tool chain is familiar to Unix users for its holy triad of commands: configure
, make
, and install
.
Like almost anything related to Linux, there is a universe of information about autotools and the build and compile process for the source code. As this book is a mere dust mote in that universe, we can only cover the basics here.
Note
Most of the software you'll want is only released in the tarball (source code) form. These are just compressed archives with extensions, such as .tar.gz
, .tar.xz
, or .tar.bz2
.
Documentation standards
In the open source world, developers generally ship their source code with the README
files intended to provide guidance on the compile process for their tarball. The README
file can serve as a starting point to build the package from scratch. Unfortunately, these README
files can often be cryptic or poorly written. Although frustrating, it is inevitable that you will frequently find yourself Googling for more information about how to install a package.
Compiling on BeagleBone Black
Although the board's 1.7 GHz ARM chip is pretty snappy for most embedded applications, compiling and installing software directly on the BBB can be pretty poky and even painful. Ideally, building a large package with multiple dependencies will be far speedier on a dedicated desktop with bushels of RAM. However, for the purposes of simplicity, we'll forge ahead with how to compile on our board.
Autotools contains several utility programs:
- Autoconf: This creates a configure shell script for the source code that runs tests to determine the build environment.
- Automake: This generates files called
Makefiles
that track the dependencies for the code that you run with amake
utility. - Libtool: This is a script that provides a frontend to the often complex assortment of shared objects, such as compilers, linkers, and libraries that an application requires. In the Windows world, developers more commonly know this animal as dynamic link libraries or DLLs.
For most occasions when you compile and install a source file package, you will rely on three common commands, which must be run in the directory where they reside:
./configure
: This runs a script that configures themake
file. It serves to customize the package to the system where it will be running. The./
tells the Linux shell that the script is in the current directory.make
: This is the command that executes the make files in your source code. The make files contain the shell commands that compile the necessary files for assembling the software package.make install
: This is simply themake
command, but with an additional option called target. It takes the compiled files from Step 2 and installs them.
The make
and make install
commands almost always require super user privileges to execute, so sudo make
and sudo make install
is your frequent companion.
When you run make
, you can further refine what the script does with other targets. Here are other commonly used options:
make all
: This is somewhat redundant to just using make, but you may occasionally find aREADME
file recommending it. Target compiles the entire program, including its libraries and documentation.make install-strip
: This is the same asmake install
, strips out debugging symbols, and is not typically recommended unless you're certain that the program has no bugs.make uninstall
: This is the opposite ofmake install
because it deletes all the installed files.make clean
: This cleans and erases what has been built (the opposite ofmake all
).make distclean
: This erases anything that the./configure
command created.make check
: This runs a test suite if one exists for the source.make installcheck
: This performs installation checks on the installed program (if needed).make dist
: This creates a distribution tarball for the program and outputsPACKAGE-VERSION.tar.gz
.
See also
- For a more detailed usage of the autotools toolset and further explanation on how to change the default behaviors and the options to build customized packages in order to suit your specific purpose, refer to https://autotools.io/index.html
- Refer to https://www.gnu.org/software/libtool/ for more details on Libtool
- You can deep dive into autotools arcana with a bazillion examples at https://www.lrde.epita.fr/~adl/autotools.html
Now, onward and upward with the recipes.
See also
- For a more detailed usage of the autotools toolset and further explanation on how to change the default behaviors and the options to build customized packages in order to suit your specific purpose, refer to https://autotools.io/index.html
- Refer to https://www.gnu.org/software/libtool/ for more details on Libtool
- You can deep dive into autotools arcana with a bazillion examples at https://www.lrde.epita.fr/~adl/autotools.html
Now, onward and upward with the recipes.
Compile and install Git from source
Our first recipe is a basic scenario of building from a source file and then installing it on your BBB. In this case, we will work with Git, the illustrious software version control system.
We could have cheated and just stuck with the version of Git that is already handily installed on the current Debian distro for the BBB. Let's check it:
$ git --version git version 2.0.2
This tells us that the current prebuilt Git binary offered for armh on the Debian repository is version 2.0.2. Yet, if we go to the Git website (http://git-scm.com/), you will learn that there is a newer version. So, let's install the latest and greatest from the source.
How to do it...
Perform the following steps:
- To get the dependencies or associated libraries, we'll need to start by grabbing the libraries that Git requires:
curl
,zlib
,openssl
,expat
, andlibiconv
with the following command:$ sudo apt-get install libcurl4-gnutls-dev libexpat1-dev gettext libz-dev libssl-dev
- As we are about to download the package source files and the compiled code, we should set up a directory where we can consistently manage everything, as shown in the following command:
$ mkdir /home/debian/packages/
- With the libraries installed, it's tarball time, so get Git using the following command:
$ wget -P /home/debian/packages https://www.kernel.org/pub/software/scm/git/git-2.6.2.tar.xz
The
-P
option pointswget
to the specified directory.Note
The preceding tarball version will likely be superseded by the more current code. Check for the latest Git tarball at http://git-scm.com/. This link will likely refer you to a code repository. There, you'll look for a file with the
git-0.0.0.tar.xz
naming convention, along with another possible digit depending on the version. - Navigate to the directory and
untar
it as follows:$ cd packages $ tar -xf git-2.6.2.tar.xz
- Then, go to the new directory created with the following code:
~/packages$ cd git-2.6.2
Note
In the untarred folder, search for the
INSTALL
file. This file provides guidance on alternative directories for installation purposes than the one we will perform here. - Now, we are ready to install git. For each stage of this process, wait for the terminal window to default back to your working prompt before proceeding. We will begin with
./configure
:$ ./configure
- Next, the
make
file needs our attention with the command:$ sudo make
In this case, and if you're building the package directly on your BBB, the compilation may take more than 20 minutes; other packages can take considerably longer. So, be patient and wait for the default prompt.
- Once all the files have been crunched and compiled, we need to install the package, a step that can often finish quickly, as shown in the following code:
$ sudo make install
- Finally, let's see how we performed compared to our prior 2.0.2 version with the following command:
$ git --version git version 2.X.x
Voila! The freshest baked version of Git is now at your board's disposal.
How to do it...
Perform the following steps:
- To get the dependencies or associated libraries, we'll need to start by grabbing the libraries that Git requires:
curl
,zlib
,openssl
,expat
, andlibiconv
with the following command:$ sudo apt-get install libcurl4-gnutls-dev libexpat1-dev gettext libz-dev libssl-dev
- As we are about to download the package source files and the compiled code, we should set up a directory where we can consistently manage everything, as shown in the following command:
$ mkdir /home/debian/packages/
- With the libraries installed, it's tarball time, so get Git using the following command:
$ wget -P /home/debian/packages https://www.kernel.org/pub/software/scm/git/git-2.6.2.tar.xz
The
-P
option pointswget
to the specified directory.Note
The preceding tarball version will likely be superseded by the more current code. Check for the latest Git tarball at http://git-scm.com/. This link will likely refer you to a code repository. There, you'll look for a file with the
git-0.0.0.tar.xz
naming convention, along with another possible digit depending on the version. - Navigate to the directory and
untar
it as follows:$ cd packages $ tar -xf git-2.6.2.tar.xz
- Then, go to the new directory created with the following code:
~/packages$ cd git-2.6.2
Note
In the untarred folder, search for the
INSTALL
file. This file provides guidance on alternative directories for installation purposes than the one we will perform here. - Now, we are ready to install git. For each stage of this process, wait for the terminal window to default back to your working prompt before proceeding. We will begin with
./configure
:$ ./configure
- Next, the
make
file needs our attention with the command:$ sudo make
In this case, and if you're building the package directly on your BBB, the compilation may take more than 20 minutes; other packages can take considerably longer. So, be patient and wait for the default prompt.
- Once all the files have been crunched and compiled, we need to install the package, a step that can often finish quickly, as shown in the following code:
$ sudo make install
- Finally, let's see how we performed compared to our prior 2.0.2 version with the following command:
$ git --version git version 2.X.x
Voila! The freshest baked version of Git is now at your board's disposal.
Debugging
Reality check: stuff breaks, especially with software. And when your software is broken, it makes it really hard to get things done with your hardware. So, the truth of the matter is (you already know this if you're an experienced programmer) that most of your time when you create some shiny new software thing, a considerable amount of time is spent on fixing and debugging your code.
In Linux Land, GDB (GNU project debugger) rules the roost as the standard debug tool. It is the go to app that provides a window to what is happening in the guts of another program and allows you to saunter through the source code line by line when the program runs. Conveniently, it comes preloaded on the Debian distribution for your BBB.
GDB provides four key things needed for fast and efficient debugging:
- Starts your program and illuminates anything that may affect the program's behavior
- Stops your program on the specified conditions
- Investigates an error or anomaly and tells you what was happening at the time a program crashed
- Tweaks code in your program, allowing you to quickly stomp one bug and go on to get another
See also
Check these links for more guidance on debugging:
See also
Check these links for more guidance on debugging:
Debug a simple C-code application from the command line using GDB
GDB is frequently used to dig into problems you may have with a C or C++ program that you may have written. Alternatively, you can run GDB to debug an executable or binary. In this section, we will perform the former.
One of the most typical entry points to understand how to debug using GDB is by running simple examples of executables written in C or C++. Many of the software resources available for developing on hardware platforms such as BeagleBone Black, commonly rely on C or C++. These are the core, low-level (and mid-level) languages needed for deep manipulation of the machinery. Indeed, most of the binaries that you will often load to your BBB are written in one or both of these two languages. They also serve as a vital bridge between high-level and low-level programming, which we will see in later chapters.
If you are already an Arduino user or even a Raspberry Pi developer, this is old news because you already know that the Arduino processing language is largely a simplified version of C/C++. If you are a newcomer, don't worry because the examples we use are very basic and will not require advanced knowledge of C or C++. Also, any kind of in-depth analysis at either of these two programming languages is beyond the scope of this book.
We will begin by serving up a small piece of C code on the BBB so that you can see what the debugger output can show us. Then, based on GDB's forensics, we will fix the code.
How to do it...
Perform the following steps to debug a C-code application from the command line using GBD:
- Log in as a root user with the following command:
$ sudo su -i
- Now, navigate to our
projects
directory as follows:# cd bbb_recipe_book/projects
- Then, create a new subdirectory called
debug
and navigate to it with the following code:# mkdir debug # cd debug
Now, open the
nano
text editor, create the C file, and call itmajor_tom_gdb.c
,as shown in the following code:# nano majortom_gdb.c
Copy and paste the following code to the
nano
editor window as follows://majortom_gdb.c #include <stdio.h> #include <stdlib.h> #include <string.h> size_t majortom_len (const char *s) { return strlen (s); } int main (int argc, char *argv[]) { const char *a = NULL; printf ("The number of characters in Major Tom string a = %d\n", majortom_len (a)); exit (0); }
Note
If you run into problems copying and pasting the code, you can download the code from https://github.com/HudsonWerks/debug-samples/blob/master/majortom_gdb.c
- Save and close the file and press Ctrl + x; when prompted type
y
for yes and then press return (Enter)key. - Now, we will compile the file using a C-compiler command with options:
# gcc majortom_gdb.c -g -o majortom_gdb
Here is a breakdown of the options in the command:
gcc
: This is the basic compile command for a C program-g
: This generates the symbolic debugging information or symbols that GDB can understand within a compiled program-o
: This specifies the name of the compiled file
The compiler will output a file called majortom_gdb (no file type).
Note
The current Debian distribution comes preloaded with the C/C++ compiler. If for some reason, you get errors that indicate that the compile will not run or is not present, install the compiler with
$ sudo apt-get install g++
.Run the compiled file in
gdb
using the following code:# gdb ./majortom_gdb
This is how the output should look:
GNU gdb (GDB) 7.4.1-debian Copyright (C) 2012 Free Software Foundation, Inc. License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html> This is free software: you are free to change and redistribute it. There is NO WARRANTY, to the extent permitted by law. Type "show copying" and "show warranty" for details. This GDB was configured as "arm-linux-gnueabihf". For bug reporting instructions, please see: <http://www.gnu.org/software/gdb/bugs/>... Reading symbols from /home/debian/bbb_recipe_book/projects/debug/majortom_gdb...done. (gdb)
- Note
gdb
at the end of the output. This indicates that you have started a debug session and can now use GDB commands to control the tool. So, now enter the following code:(gdb) run
Boom. Your output should show a bug: the dreaded
segfault
(the segmentation fault). The error also tells us that we attempted to access an invalid memory address, as shown in the following code:Starting program: /home/debian/bbb_recipe_book/projects/debug/majortom_gdb Program received signal SIGSEGV, Segmentation fault. 0xb6f45904 in strlen () from /lib/arm-linux-gnueabihf/libc.so.6 (gdb)
The good news is that GDB just told us that the problem lies with
strlen
, a standard C library function that determines the length of a string. However, the function requires a nonNULL string in order to run properly. Thus, our NULL value threw off the bug. So, now we can fix it. - Now, exit out of GDB with the following code:
(gdb) quit
- Then, open your C file again as follows:
~/projects/debug# sudo nano majortom_gdb.c
In line 13, change
NULL
to the"Ground Control to Major Tom"
string with double quotes, as shown in the following code:const char *a = "Ground Control to Major Tom";
- Now, save, close, and press Ctrl + x; when prompted type
y
for yes and then press return (Enter)key. - Recompile the file as follows:
# gcc majortom_gdb.c -g -o majortom_gdb
- Then, run the compiled file in GDB again, as shown in the following code:
# gdb ./majortom_gdb
- Now, let's begin the debug session with the following code:
(gdb) run
If all goes as planned, your code should no longer
segfault
, but show the output similar to the following code:Starting program: /home/debian/bbb_recipe_book/projects/debug/majortom_gdb The number of characters in Major Tom string a = 27 [Inferior 1 (process 6020) exited normally] (gdb)
This enlightens us to the fact that our string "
Ground Control to Major Tom
" contains 27 characters. - Finally, exit GDB normally by entering the following code:
quit
See? Nothing to it. C code. Crash. Debug. Fix C code. All on a very little Linux box.
See also
In Chapter 7,Applied Recipes – Sound, Picture, and Video, we will run a more advanced recipe, where we will compile a SIP/VOIP package for the purpose of exploring sound and video. The compilation will include debugging examples with further use of GDB.
How to do it...
Perform the following steps to debug a C-code application from the command line using GBD:
- Log in as a root user with the following command:
$ sudo su -i
- Now, navigate to our
projects
directory as follows:# cd bbb_recipe_book/projects
- Then, create a new subdirectory called
debug
and navigate to it with the following code:# mkdir debug # cd debug
Now, open the
nano
text editor, create the C file, and call itmajor_tom_gdb.c
,as shown in the following code:# nano majortom_gdb.c
Copy and paste the following code to the
nano
editor window as follows://majortom_gdb.c #include <stdio.h> #include <stdlib.h> #include <string.h> size_t majortom_len (const char *s) { return strlen (s); } int main (int argc, char *argv[]) { const char *a = NULL; printf ("The number of characters in Major Tom string a = %d\n", majortom_len (a)); exit (0); }
Note
If you run into problems copying and pasting the code, you can download the code from https://github.com/HudsonWerks/debug-samples/blob/master/majortom_gdb.c
- Save and close the file and press Ctrl + x; when prompted type
y
for yes and then press return (Enter)key. - Now, we will compile the file using a C-compiler command with options:
# gcc majortom_gdb.c -g -o majortom_gdb
Here is a breakdown of the options in the command:
gcc
: This is the basic compile command for a C program-g
: This generates the symbolic debugging information or symbols that GDB can understand within a compiled program-o
: This specifies the name of the compiled file
The compiler will output a file called majortom_gdb (no file type).
Note
The current Debian distribution comes preloaded with the C/C++ compiler. If for some reason, you get errors that indicate that the compile will not run or is not present, install the compiler with
$ sudo apt-get install g++
.Run the compiled file in
gdb
using the following code:# gdb ./majortom_gdb
This is how the output should look:
GNU gdb (GDB) 7.4.1-debian Copyright (C) 2012 Free Software Foundation, Inc. License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html> This is free software: you are free to change and redistribute it. There is NO WARRANTY, to the extent permitted by law. Type "show copying" and "show warranty" for details. This GDB was configured as "arm-linux-gnueabihf". For bug reporting instructions, please see: <http://www.gnu.org/software/gdb/bugs/>... Reading symbols from /home/debian/bbb_recipe_book/projects/debug/majortom_gdb...done. (gdb)
- Note
gdb
at the end of the output. This indicates that you have started a debug session and can now use GDB commands to control the tool. So, now enter the following code:(gdb) run
Boom. Your output should show a bug: the dreaded
segfault
(the segmentation fault). The error also tells us that we attempted to access an invalid memory address, as shown in the following code:Starting program: /home/debian/bbb_recipe_book/projects/debug/majortom_gdb Program received signal SIGSEGV, Segmentation fault. 0xb6f45904 in strlen () from /lib/arm-linux-gnueabihf/libc.so.6 (gdb)
The good news is that GDB just told us that the problem lies with
strlen
, a standard C library function that determines the length of a string. However, the function requires a nonNULL string in order to run properly. Thus, our NULL value threw off the bug. So, now we can fix it. - Now, exit out of GDB with the following code:
(gdb) quit
- Then, open your C file again as follows:
~/projects/debug# sudo nano majortom_gdb.c
In line 13, change
NULL
to the"Ground Control to Major Tom"
string with double quotes, as shown in the following code:const char *a = "Ground Control to Major Tom";
- Now, save, close, and press Ctrl + x; when prompted type
y
for yes and then press return (Enter)key. - Recompile the file as follows:
# gcc majortom_gdb.c -g -o majortom_gdb
- Then, run the compiled file in GDB again, as shown in the following code:
# gdb ./majortom_gdb
- Now, let's begin the debug session with the following code:
(gdb) run
If all goes as planned, your code should no longer
segfault
, but show the output similar to the following code:Starting program: /home/debian/bbb_recipe_book/projects/debug/majortom_gdb The number of characters in Major Tom string a = 27 [Inferior 1 (process 6020) exited normally] (gdb)
This enlightens us to the fact that our string "
Ground Control to Major Tom
" contains 27 characters. - Finally, exit GDB normally by entering the following code:
quit
See? Nothing to it. C code. Crash. Debug. Fix C code. All on a very little Linux box.
See also
In Chapter 7,Applied Recipes – Sound, Picture, and Video, we will run a more advanced recipe, where we will compile a SIP/VOIP package for the purpose of exploring sound and video. The compilation will include debugging examples with further use of GDB.
See also
In Chapter 7,Applied Recipes – Sound, Picture, and Video, we will run a more advanced recipe, where we will compile a SIP/VOIP package for the purpose of exploring sound and video. The compilation will include debugging examples with further use of GDB.
Debug an application remotely from Eclipse and GDB server
You are about to dive into the arcane, but necessary world of remote debugging/cross-compiling. In this chapter, we will specifically take a look at a recipe for setting up remote debugging using the GDB server.
We will set up a specific kind of environment on your client desktop, another kind of environment on your BBB, and use an IDE as a way to ease the potential collision between these two worlds.
Wait a minute! Didn't we just do a debug recipe directly on BeagleBone Black using GDB? And can't we just develop and compile right on BeagleBone Black? Yes and yes.
But your BeagleBone Black is not quite powerful enough to serve as a serious development box. Ideally, what we want to do is hand off that work to a fancier, faster, desktop box. Otherwise, you will spend many unnecessary hours testing, compiling, debugging, and watching reruns of Doctor Who while waiting for the BBB to complete its tasks.
Why don't we just make something on one box and move it over to another box? Hmm. Not so fast. If you want to create or debug an application on a nonBBB board and output a binary or chunk of code to run it on an ARM Linux board like the BBB's, then you have to have the right toolset. This toolset will juggle between differing board architectures and operating system requirements.
Unfortunately, getting this toolset set up properly can be quite unpleasant. Not only does it take a fair bit of time, the process is also fraught with many opportunities for error. So, be patient and persistent in following this recipe.
Before going into the minutiae, here are the high-level steps to get remote debugging going on BeagleBone Black:
- Install and set up a virtual machine; you can skip this if your client development box is Linux.
- Install and set up a cross-compile and debug toolchain.
- Install and set up the GDB server on your BeagleBone Black.
- Install and set up Eclipse, our IDE of choice.
Nothing to it, right? Not quite...
How to do it...
Part I: Set up Virtual Machine—Mac OSX
On your client box, we will set up a virtual machine (VM) with a Linux distribution on board. There are a number of sources for this, but we will use Oracle's free virtual box (once again, if you are already using this book and its recipes with a Linux box as your client machine, installing a VM is not necessary).
Note
All the steps in this section occur on either your desktop client box or a virtual machine, not on BeagleBone Black.
Download and install the VM from https://www.virtualbox.org/. When finished, open the application. Perform the following steps
- Download a Linux distribution that you will load to Virtual Box's virtual machine environment. We used an i386 net install of Debian Wheezy available from debian.org at https://www.debian.org/releases/wheezy/debian-installer/ (download is available at http://cdimage.debian.org/debian-cd/7.6.0/i386/iso-cd/debian-7.6.0-i386-netinst.iso).
Note
You do not need to have the VM run Debian Wheezy for ARMH as the BBB does, but can use almost any flavor of Linux.
- Next, install and set up a Linux environment on the VM. In the open Virtual Box window, click on New (VM).
- Give the VM a name, something clever like Debian Wheezy.
- From the drop-down options:
- Choose Linux
- Then choose, Debian (32-bit) according to the type of
.iso
you downloaded
- Then, click on Continue.
- Allocate 1024 MB of memory instead of the default 512 MB. Then, click on the Next button.
- For the hard drive, unless you have another virtual hard disk set up and want to use it, leave it with the default setting: Create a virtual hard drive now. Then, click on Create.
- For the hard drive file type, leave the default VDI setting. Then, click on Continue.
- For the storage on the physical hard drive, check whether you prefer the VM to have a fixed drive space allocation (which can be faster once built) or a dynamic storage capacity (which will only expand as needed). I kept mine at dynamically allocated. Click on Continue.
- For the file location and size, click on Create. This closes the setup window and returns you to the main dashboard.
- At the dashboard, you should now see the VM we just created: Debian Wheezy. Before running the VM, we need to configure it some more. So, click on Settings.
Follow these settings:
- General | Advanced | Shared Clipboard. Choose bidirectional because you will want to share the clipboard data in both the directions between the client box (in our case, Mac OS X) and the Debian VM. You will still need to follow additional steps to get this function working. Navigate to the following:
System | Storage | Controller IDE—Click on the (+) sign (Add CD/DVD device) to open a browse directory window. Click on Choose Disk.
Navigate to the folder where you downloaded the
.iso
file of your preferred Linux distro. The filename will be something similar todebian-x.y.z-i386-netinst.iso
or some variant on the architecture that you chose. Then, click on Open.
- General | Advanced | Shared Clipboard. Choose bidirectional because you will want to share the clipboard data in both the directions between the client box (in our case, Mac OS X) and the Debian VM. You will still need to follow additional steps to get this function working. Navigate to the following:
Your OS should now be loaded. But now, we need to have the OS actually installed in its normal fashion on the virtual drive that you set up. Perform the following steps:
- On the dashboard, while making sure that your new Debian VM is selected, click on the Start button.
- On your first bootup, you will be presented with a Debian setup window. Choose INSTALL.
You will then be taken through quite a few setup windows, including choosing language, region and keyboard preferences, network options, password and user setup, and other configuration options that I will not elaborate here. Configure as you see fit, while clicking on the Continue button until you end up with the hard disk partitioning sequence. Make your choices there according to your preference. In most cases, choosing the default option should be fine.
Note
Keep in mind that an entire OS is being installed on your host machine, so this step will take a while. Also, remember that this new OS is being installed on the Virtual Machine environment and not affecting or modifying your client desktop.
- Once the Debian installation and setup is completed, you will end up at the Debian GUI login screen. Log in and you will finally arrive at the desktop.
- Let's open the terminal window in our new Debian environment and perform a basic ping test on BeagleBone Black. We want to make sure that we can communicate with it via our VM as follows:
$ ping 192.168.7.2
You should get consistent pings.
Adding cut and paste to VM
We now need to implement an additional functionality to the virtual box that will drive you mad if you do not add it: the cut-and-paste function. When you use Mac OS X as your client machine, Virtual Box, like most virtual machine software, does not include cut-and-paste by default. Instead, they have given us a series of 15 steps (yes, 15!). Oracle/Virtual Box refers to this function as Guest Additions. Here we go:
- Let's begin by installing some external kernel modules on your VM. So, with a terminal window open in the Debian virtual machine on your client desktop, run the following command as a root user:
$ sudo -i ~# apt-get install dkms
- Next, back on your client desktop (Mac OS X), we have to locate a very buried
.iso
file that contains the code to add the guest additions with its cut and paste feature. In Finder, navigate to Applications | Virtualbox.app | Show Package Contents.This will open all the hidden directories in the package, including our target directory and file.
Then, navigate to Contents | MacOS | VBoxGuestAdditions.iso.
- Find and copy the
VBoxGuestAdditions.iso
file to a place where you can find it on your machine. - Back in your open Virtual Box, in Debian Wheezy | Settings | Storage, click on the small CD icon at the bottom of the screen and select Choose a Virtual CD/DVD disk file.
Another way to perform the same thing is from the drop-down menus at the top of the screen (not in the VM/Debian window, but the virtual machine menu options at the very top of your desktop machine. There, you can choose Devices | CD/DVD devices | IDE (IDE Primary Master) | Choose a Virtual/CD/DVD disk file.
- Browse to where you put the
VBoxGuestAdditions.iso
file and select it. The.iso
file should now appear in the CD/DVD drive options. Click on OK and restart the VM. - With the terminal window open in your Debian VM, run the following two commands:
~# apt-get update ~# apt-get upgrade
- Now, confirm that you have the
make
and GNU C compiler installed, which should already be on the distribution that you installed. Check it with the following code:~# gcc --version
- If you don't get an output that shows the version, but a
command not found
error, you will need to install it as follows:~# apt-get install make gcc
- Reboot your Virtual Box machine.
- Determine the exact version of your kernel with the following code:
~# uname -a
- Install the correct version of the
linux-headers
package. Replace the following version numbers with the version number shown in the prior step:~# apt-get install linux-headers-2.6.26-2-68
This may take some time; just wait for the installation to finish and return to your terminal prompt.
- Restart your VM with the following code:
# reboot
- From the screen options, select Machine | options | General and then click on the Advanced tab. In the Shared Clipboard dropdown, select the Bidirectional option.
The cut-and-paste functionality between your client host box (in our case, Mac OS X) and your virtual machine environment should now be enabled.
- Before moving one though, we need to verify that the cut-and-paste function is working. From your Debian Wheezy virtual machine window, navigate to Applications | Accessories | gedit Text Editor and open a new file, as shown in the following screenshot:
- From the open file window, enter
Ground Control
and then select Edit | Copy. Then, navigate to your client desktop (Mac/Windows machine, and so on), open a simple text editor, and select Paste. Hopefully,Ground Control
will be pasted to the window. - We want to check the bidirectional functionality, so now enter
Major Tom
in (Mac/Windows) text editor on the desktop and press Ctrl + c (copy). Now, switch back to the VM editor window and then select Edit | Paste.Major Tom
should be pasted successfully to thegedit
window. - Reboot the VM and then log back in as the root user with the following code:
# sudo -i
- Add your username to the
sudo
group as follows:# adduser username sudo
- Then, use the
fdisk
command to check whethersudo
is working properly. The-v
option will check the version offdisk
installed on your VM. You should get a prompt for a user password, as shown in the following code:# sudo fdisk -v
The screen output should show the version of
fdisk
that is installed, and there should be no errors about permissions. - Install
ssh
. We already use it on the BBB. Now, we need to add it to our VM. SSH gives Eclipse the ability to connect and transfer files to BeagleBone Black usingscp
, a secure network protocol. Install it with the following code:# sudo apt-get install ssh
Part II: Installing gdbserver on BeagleBone Black
We need this package on board the BBB so that we can run gdb
from afar or from another box. Perform the following steps:
- First, download the Debian installation package of
gdbserver
forarmhf
(the BBB-native architecture) on your VM as follows:# wget http://http.us.debian.org/debian/pool/main/g/gdb/gdbserver_7.4.1+dfsg-0.1_armhf.deb
- Now, use
scp
to transfer the package to the BBB, as shown in the following code:# scp gdbserver_7.4.1+dfsg-0.1_armhf.deb root@192.168.7.2:~
- You should get a password prompt for the root user on BeagleBone. Log in and install the package as follows:
# ssh root@192.168.7.2 root@arm# dpkg -i gdbserver_7.4.1+dfsg-0.1_armhf.deb
- When finished, log out by exiting the SSH session, as shown in the following code:
root@arm# exit
Part III: Installing and setting up the toolchain
This part and the next one are the hairiest bits of the process; many online tutorials on this subject purport to deliver a working toolchain lashed to an IDE, though few of them actually deliver.
Fortunately for us, engineer and blogger Aaron Clarke's very clear steps at http://bit.ly/1x7TGUY provide superb guidelines for a successful toolchain and the Eclipse IDE setup. The vast majority of the credit for the next two parts of the recipe go to Mr. Clarke.
Note
We chose not to include screenshots of the process because doing so would have made the recipe considerably longer. However, you can find a more graphical version of this recipe online at Aaron Clarke's blog, which includes a version for Debian Jessie at http://blog.embeddedcoding.com/2015/05/beaglebone-black-development-part-6.html.
Here we go.
Perform the following steps:
- At the terminal prompt on your Debian VM, if you are not already logged in as root, do so now with the following command:
$ sudo -i
- Create a new directory where you will download the toolchain and then navigate to that directory, as shown in the following code:
root@debian:/home/user# mkdir bbb-tools root@debian:/home/user# cd bbb-tools
- Using
wget
, download the toolchain from the following link to the directory that we just created:# wget -c https://launchpad.net/linaro-toolchain-binaries/trunk/2013.10/+download/gcc-linaro-arm-linux-gnueabihf-4.8-2013.10_linux.tar.xz
- Then, untar the file with the following code:
# tar xf gcc-linaro-arm-linux-gnueabihf-4.8-2013.10_linux.tar.xz
- Now, run the
echo
command to create thebbb-vars
file; this will be used to test that our environment is set up properly, as shown in the following code:# echo "export CC=`pwd`/gcc-linaro-arm-linux-gnueabihf-4.8-2013.10_linux/bin/arm-linux-gnueabihf-" > bbb-vars
- Verify that the command worked. The
bbb-vars
file should appear in the directory as follows:root@debian:/home/user/bbb-tools# ls bbb-vars
- Set up the environment for a remote test by sourcing the
bbb-vars
file. Take a look at the command preceding the (.
) is the file location:root@debian:~# ./home/user/bbb-tools/bbb-vars
- Now, verify that the toolchain version we installed is correct using the following code:
root@debian:~# ${CC}gcc –-version arm-linux-gnueabihf-gcc (crosstool-NG linaro-1.13.1-4.8-2013.10 - Linaro GCC 2013.10) 4.8.2 20131014 (prerelease)Copyright (C) 2013 Free Software Foundation, Inc.This is free software; see the source for copying conditions. There is NOwarranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE
Part IV: Installing and setting up the Eclipse IDE
Perform the following steps:
- We will first install Eclipse on our VM with the following code:
root@debian:~# sudo apt-get install eclipse eclipse-cdt
Then, open Eclipse and set up a workspace by closing the welcome screen and navigating to Window | Show view | C/C++ Projects.
- Create a new C project by navigating to File | New | C Project.
- Give the project a name:
bbb_ground_control
. - Select Project type | Hello World ANSI C Project.
- Then, select Toolchain Cross GCC and click on Next.
- Enter the basic settings, such as the author name, in the next window.
- Click on Next to bring up the Select Configurations window.
- Now, click on the Advanced settings to bring up a Properties window.
- From the left-hand side, navigate to C/C++ Build | Settings to bring up Tool Settings for the Debug configuration.
- Choose the Tool Settings tab, then fill the Prefix and Path fields in the following manner:
Prefix:
arm-linux-gnueabihf-
Note
Be sure to include the hyphen (
-
) at the end of the preceding prefix.Path:
/home/user/bbb-tools/gcc-linaro-arm-linux-gnueabihf-4.8-2013.10_linux/bin
- Then, click on OK.
- This brings up another C Project window, which annoyingly asks you to repeat what you just did in the prior step. This may be a bug, but do it anyway:
Prefix:
arm-linux-gnueabihf-
Path:
/home/cah/bbb-tools/gcc-linaro-arm-linux-gnueabihf-4.8-2013.10_linux/bin
- Then, click on Finish.
- The sample code runs and you get an error:
Symbol 'EXIT_SUCCESS' could not be resolved
. Aaargh!The error says that some C code symbols cannot be resolved by the compiler. Not to worry though. This error can be ignored because according to the Eclipse documentation, it is inaccurate and does not affect the successful operation of the application.
- Now, we will build the project. On the Eclipse main menu, select Project | Build All. Then, open the Console window to see the build output messages. You should see the compiler prefix being used for the
gcc
compiler as follows:00:24:52 **** Build of configuration Debug for project bbb_ground_control ****make all Building file: ../src/bbb_ground_control.cInvoking: Cross GCC Compilerarm-linux-gnueabihf-gcc -O0 -g3 -Wall -c -fmessage-length=0 -MMD -MP -MF"src/ bbb_ground_control.d" -MT"src/ bbb_ground_control.d" -o "src/ bbb_ground_control.o" "../src/ bbb_ground_control.c"Finished building: ../src/ bbb_ground_control.c Building target: bbb_ground_control Invoking: Cross GCC Linkerarm-linux-gnueabihf-gcc -o " bbb_ground_control " ./src/ bbb_ground_control.o Finished building target: bbb_ground_control 00:24:52 Build Finished (took 172ms)
- For the Eclipse remote connection setup, on the main menu, click on Run | Run Configurations.
- Select C/C++ Remote Application. Click twice on this to open another dialog window.
- A drop-down option should show bbb_Hello_World Debug. Click on the New button in the middle of the window to create a project debug run configuration. Click on the New button next to Connection in the Main tab.
- This brings up the New Connection window.
- Select Linux and click on Next.
- This brings up a window with the connection information. Enter BeagleBone Black IP address for Host name and name the Connection name and Description both as
BeagleBone Black
:- Host name:
192.168.2.7
- Connection name:
Beaglebone Black
- Description:
Beaglebone Black
- Host name:
- Click on Next.
- In the New Connection/Files window, select the
select.ssh
files and then click on Next. - In the New Connection/Processes window, select
processes.shel.linux
. Then, click on Next. - In the New Connection/Shells window, select
ssh.shells
. Then, click on Next. - In the New Connection/Ssh Terminals window, select
ssh.terminals
and click on Finish. - You will end up back at the Run Configurations window. For Connection, choose BeagleBone Black, not Local.
- Click on Properties next to Connection. A window will come up, so select Remote workspace location.
- Enter a path to your project on BeagleBone Black. For the sake of simplicity, you should probably follow what we did and input
/root
. - Click on OK. This takes you back to the Run Configurations window.
In the following steps, we will perform two key things: configure our remote paths on the BBB and give our application permission to execute.
- At the bottom of the Run Configurations screen are two fields. Input the following:
remote absolute file path for C/C++ application:
/root/test_project/bbb_ground_control
commands to execute before application:
chmod +x /root/test_project/bbb_ground_control
Note
Choose a path on BeagleBone Black where the
bbb_ground_control
executable file will be placed. In our example, it is/root/test_project/bbb_ground_control
, wherebbb_ground_control
is the name of the binary file that we will compile. The purpose of thechmod +x
command is to give our program permission to execute. - Click on Apply. We are almost there. Be patient and hang on tight.
- From the terminal window on the VM, we have a couple more things to perform on the BBB itself, which is to mirror what we just input in the two fields in Eclipse. First, log in with the following code:
# sudo ssh 192.168.7.2
- Answer
yes
when promptedare you sure
. - Enter the root password for the BBB:
root
. You should now be logged in to the BBB. - Run the commands to duplicate what we just did in Eclipse, which means that we need to create a new directory, navigate to it and then run the following command to give the application permission to execute:
root@beaglebone:~# mkdir test_project root@beaglebone:~# cd test_project root@beaglebone:~# chmod a+w .
- Now, exit the SSH session on BeagleBone Black with the following code:
root@beaglebone:~# exit
- Back in the VM Eclipse window, click on Run.
- Another pop-up window will appear. Enter the user and password as
root
. Click on them and agree to the next few prompts from the BBB.The last few steps are focused on how to set up a remote debug session.
- In your terminal window, navigate to the project
Debug
path with the following code:# cd ~/bbb-eclipse-workspace/bbb_ground_control/Debug
- Now, we will perform a little obscure but necessary step when you run GDB: create an invisible file called
.gdbinit
. This is an initialization file that resides in the debug directory and automatically loads and parses when you run GDB.Typically, you would populate this file with any required commands. However, for our current recipe, the file remains empty, although it needs to remain present for GDB's proper operation.
- We could use
nano
to create the file because we used this editor in the earlier chapters. However, there is another command that actually generates the file on the fly, saves it, and places it in whatever directory you have entered, as shown in the following code:# touch .gdbinit
- Make sure that the file was created with the following code:
# ls
Hmm. It isn't there!
To figure out what is happening, this is a case where using different options with a command is vital. With the
ls
command, we want to append the command with the-a
option. So, try again using the following code:# ls -a
The
gdbinit
file should now appear in the directory's lineup. - Back in the Eclipse window, select Window | Open Perspective | Other. Then, select Debug. This will shift the window views to a debug-centric UI.
- From the top menu, select Run | Debug Configurations. In the window that opens, select C/C++ Remote Application | bbb_ground_control Debug.
Hold on tight. Almost done.
- Select the Debugger tab. This shows us more tabs because we haven't had our fill of tabs or options yet.
- Now, select the Main tab. Here, we need to populate the two fields: GDB Debugger (the executable in the toolchain directory) and the GDB command file (the directory where we created the .gdbinit file). To facilitate this step, you should be able to browse the relevant directories and grab the right paths as follows:
GDB Debugger:
/home/user/bbb-tools/gcc-linaro-arm-linux-gnueabihf-4.8-2013.10_linux/bin/arm-linux-gnueabihf-gdb
GDB command file:
/home/user/bbb-eclipse-workspace/bbb_ground_control/Debug/.gdbinit
- Then, click on Apply. I like this part.
- Now, we finally get to test the whole shebang with Debug run. Let me repeat and this time with bugles and proper fanfare: we will test everything we just did and start a Debug session.
So, at the bottom of the still open window, click on Debug. Hold your breath! This will start the remote session with the BBB and finish the cycle just after the
main()
line in your.c
file.Note
You may get another login prompt from your BeagleBone Black. Just do the same drill:
user = root
andpassword = root
.If all went as planned and the gremlins stay home, you should see the following output on your Eclipse console screen:
Last login: DAY MO DATE TIME YEAR from 192.168.7.1 echo $PWD'>' chmod +x /root/test_project/bbb_ground_control;gdbserver :2345 /root/test_project/bbb_ground_control;exit root@beaglebone:~# echo $PWD'>' /root> root@beaglebone:~# chmod +x /root/test_project/bbb_ground_control;gdbserver :2345 /root/test_project/bbb_ground_control;exit Process /root/test_project/bbb_ground_control created; pid = 2910 Listening on port 2345 Remote debugging from host 192.168.7.1
- Since the ultimate goal of all this effort was to actually perform some debugging on a program, now you can really get to work. Make sure your
bbb_ground_control.c
window is selected. Then, at the top, choose Run. - From the drop-down list, you will see the basket of debug commands now ready for your able, debug-twitchy fingers.
- If you made it to this point, this recipe has one last set of command ingredients:
# Go to actual cabinet on actual shelf # Take out bottle of single malt scotch # Pour dram, perhaps two # Lean back head and drink # Congratulate Major Tom on a good test flight
There's more…
A thorough review of how to debug is beyond the scope of this book. Fortunately, there are ample resources to learn more. Here are a few:
- RMS's gdb debugger tutorial is available at http://www.unknownroad.com/rtfm/gdbtut/gdbtoc.html
- For a deeper understanding of GDB and the
.gdbinit
file, refer to http://www.dirac.org/linux/gdb/03-Initialization,_Listing,_And_Running.php
How to do it...
Part I: Set up Virtual Machine—Mac OSX
On your client box, we will set up a virtual machine (VM) with a Linux distribution on board. There are a number of sources for this, but we will use Oracle's free virtual box (once again, if you are already using this book and its recipes with a Linux box as your client machine, installing a VM is not necessary).
Note
All the steps in this section occur on either your desktop client box or a virtual machine, not on BeagleBone Black.
Download and install the VM from https://www.virtualbox.org/. When finished, open the application. Perform the following steps
- Download a Linux distribution that you will load to Virtual Box's virtual machine environment. We used an i386 net install of Debian Wheezy available from debian.org at https://www.debian.org/releases/wheezy/debian-installer/ (download is available at http://cdimage.debian.org/debian-cd/7.6.0/i386/iso-cd/debian-7.6.0-i386-netinst.iso).
Note
You do not need to have the VM run Debian Wheezy for ARMH as the BBB does, but can use almost any flavor of Linux.
- Next, install and set up a Linux environment on the VM. In the open Virtual Box window, click on New (VM).
- Give the VM a name, something clever like Debian Wheezy.
- From the drop-down options:
- Choose Linux
- Then choose, Debian (32-bit) according to the type of
.iso
you downloaded
- Then, click on Continue.
- Allocate 1024 MB of memory instead of the default 512 MB. Then, click on the Next button.
- For the hard drive, unless you have another virtual hard disk set up and want to use it, leave it with the default setting: Create a virtual hard drive now. Then, click on Create.
- For the hard drive file type, leave the default VDI setting. Then, click on Continue.
- For the storage on the physical hard drive, check whether you prefer the VM to have a fixed drive space allocation (which can be faster once built) or a dynamic storage capacity (which will only expand as needed). I kept mine at dynamically allocated. Click on Continue.
- For the file location and size, click on Create. This closes the setup window and returns you to the main dashboard.
- At the dashboard, you should now see the VM we just created: Debian Wheezy. Before running the VM, we need to configure it some more. So, click on Settings.
Follow these settings:
- General | Advanced | Shared Clipboard. Choose bidirectional because you will want to share the clipboard data in both the directions between the client box (in our case, Mac OS X) and the Debian VM. You will still need to follow additional steps to get this function working. Navigate to the following:
System | Storage | Controller IDE—Click on the (+) sign (Add CD/DVD device) to open a browse directory window. Click on Choose Disk.
Navigate to the folder where you downloaded the
.iso
file of your preferred Linux distro. The filename will be something similar todebian-x.y.z-i386-netinst.iso
or some variant on the architecture that you chose. Then, click on Open.
- General | Advanced | Shared Clipboard. Choose bidirectional because you will want to share the clipboard data in both the directions between the client box (in our case, Mac OS X) and the Debian VM. You will still need to follow additional steps to get this function working. Navigate to the following:
Your OS should now be loaded. But now, we need to have the OS actually installed in its normal fashion on the virtual drive that you set up. Perform the following steps:
- On the dashboard, while making sure that your new Debian VM is selected, click on the Start button.
- On your first bootup, you will be presented with a Debian setup window. Choose INSTALL.
You will then be taken through quite a few setup windows, including choosing language, region and keyboard preferences, network options, password and user setup, and other configuration options that I will not elaborate here. Configure as you see fit, while clicking on the Continue button until you end up with the hard disk partitioning sequence. Make your choices there according to your preference. In most cases, choosing the default option should be fine.
Note
Keep in mind that an entire OS is being installed on your host machine, so this step will take a while. Also, remember that this new OS is being installed on the Virtual Machine environment and not affecting or modifying your client desktop.
- Once the Debian installation and setup is completed, you will end up at the Debian GUI login screen. Log in and you will finally arrive at the desktop.
- Let's open the terminal window in our new Debian environment and perform a basic ping test on BeagleBone Black. We want to make sure that we can communicate with it via our VM as follows:
$ ping 192.168.7.2
You should get consistent pings.
Adding cut and paste to VM
We now need to implement an additional functionality to the virtual box that will drive you mad if you do not add it: the cut-and-paste function. When you use Mac OS X as your client machine, Virtual Box, like most virtual machine software, does not include cut-and-paste by default. Instead, they have given us a series of 15 steps (yes, 15!). Oracle/Virtual Box refers to this function as Guest Additions. Here we go:
- Let's begin by installing some external kernel modules on your VM. So, with a terminal window open in the Debian virtual machine on your client desktop, run the following command as a root user:
$ sudo -i ~# apt-get install dkms
- Next, back on your client desktop (Mac OS X), we have to locate a very buried
.iso
file that contains the code to add the guest additions with its cut and paste feature. In Finder, navigate to Applications | Virtualbox.app | Show Package Contents.This will open all the hidden directories in the package, including our target directory and file.
Then, navigate to Contents | MacOS | VBoxGuestAdditions.iso.
- Find and copy the
VBoxGuestAdditions.iso
file to a place where you can find it on your machine. - Back in your open Virtual Box, in Debian Wheezy | Settings | Storage, click on the small CD icon at the bottom of the screen and select Choose a Virtual CD/DVD disk file.
Another way to perform the same thing is from the drop-down menus at the top of the screen (not in the VM/Debian window, but the virtual machine menu options at the very top of your desktop machine. There, you can choose Devices | CD/DVD devices | IDE (IDE Primary Master) | Choose a Virtual/CD/DVD disk file.
- Browse to where you put the
VBoxGuestAdditions.iso
file and select it. The.iso
file should now appear in the CD/DVD drive options. Click on OK and restart the VM. - With the terminal window open in your Debian VM, run the following two commands:
~# apt-get update ~# apt-get upgrade
- Now, confirm that you have the
make
and GNU C compiler installed, which should already be on the distribution that you installed. Check it with the following code:~# gcc --version
- If you don't get an output that shows the version, but a
command not found
error, you will need to install it as follows:~# apt-get install make gcc
- Reboot your Virtual Box machine.
- Determine the exact version of your kernel with the following code:
~# uname -a
- Install the correct version of the
linux-headers
package. Replace the following version numbers with the version number shown in the prior step:~# apt-get install linux-headers-2.6.26-2-68
This may take some time; just wait for the installation to finish and return to your terminal prompt.
- Restart your VM with the following code:
# reboot
- From the screen options, select Machine | options | General and then click on the Advanced tab. In the Shared Clipboard dropdown, select the Bidirectional option.
The cut-and-paste functionality between your client host box (in our case, Mac OS X) and your virtual machine environment should now be enabled.
- Before moving one though, we need to verify that the cut-and-paste function is working. From your Debian Wheezy virtual machine window, navigate to Applications | Accessories | gedit Text Editor and open a new file, as shown in the following screenshot:
- From the open file window, enter
Ground Control
and then select Edit | Copy. Then, navigate to your client desktop (Mac/Windows machine, and so on), open a simple text editor, and select Paste. Hopefully,Ground Control
will be pasted to the window. - We want to check the bidirectional functionality, so now enter
Major Tom
in (Mac/Windows) text editor on the desktop and press Ctrl + c (copy). Now, switch back to the VM editor window and then select Edit | Paste.Major Tom
should be pasted successfully to thegedit
window. - Reboot the VM and then log back in as the root user with the following code:
# sudo -i
- Add your username to the
sudo
group as follows:# adduser username sudo
- Then, use the
fdisk
command to check whethersudo
is working properly. The-v
option will check the version offdisk
installed on your VM. You should get a prompt for a user password, as shown in the following code:# sudo fdisk -v
The screen output should show the version of
fdisk
that is installed, and there should be no errors about permissions. - Install
ssh
. We already use it on the BBB. Now, we need to add it to our VM. SSH gives Eclipse the ability to connect and transfer files to BeagleBone Black usingscp
, a secure network protocol. Install it with the following code:# sudo apt-get install ssh
Part II: Installing gdbserver on BeagleBone Black
We need this package on board the BBB so that we can run gdb
from afar or from another box. Perform the following steps:
- First, download the Debian installation package of
gdbserver
forarmhf
(the BBB-native architecture) on your VM as follows:# wget http://http.us.debian.org/debian/pool/main/g/gdb/gdbserver_7.4.1+dfsg-0.1_armhf.deb
- Now, use
scp
to transfer the package to the BBB, as shown in the following code:# scp gdbserver_7.4.1+dfsg-0.1_armhf.deb root@192.168.7.2:~
- You should get a password prompt for the root user on BeagleBone. Log in and install the package as follows:
# ssh root@192.168.7.2 root@arm# dpkg -i gdbserver_7.4.1+dfsg-0.1_armhf.deb
- When finished, log out by exiting the SSH session, as shown in the following code:
root@arm# exit
Part III: Installing and setting up the toolchain
This part and the next one are the hairiest bits of the process; many online tutorials on this subject purport to deliver a working toolchain lashed to an IDE, though few of them actually deliver.
Fortunately for us, engineer and blogger Aaron Clarke's very clear steps at http://bit.ly/1x7TGUY provide superb guidelines for a successful toolchain and the Eclipse IDE setup. The vast majority of the credit for the next two parts of the recipe go to Mr. Clarke.
Note
We chose not to include screenshots of the process because doing so would have made the recipe considerably longer. However, you can find a more graphical version of this recipe online at Aaron Clarke's blog, which includes a version for Debian Jessie at http://blog.embeddedcoding.com/2015/05/beaglebone-black-development-part-6.html.
Here we go.
Perform the following steps:
- At the terminal prompt on your Debian VM, if you are not already logged in as root, do so now with the following command:
$ sudo -i
- Create a new directory where you will download the toolchain and then navigate to that directory, as shown in the following code:
root@debian:/home/user# mkdir bbb-tools root@debian:/home/user# cd bbb-tools
- Using
wget
, download the toolchain from the following link to the directory that we just created:# wget -c https://launchpad.net/linaro-toolchain-binaries/trunk/2013.10/+download/gcc-linaro-arm-linux-gnueabihf-4.8-2013.10_linux.tar.xz
- Then, untar the file with the following code:
# tar xf gcc-linaro-arm-linux-gnueabihf-4.8-2013.10_linux.tar.xz
- Now, run the
echo
command to create thebbb-vars
file; this will be used to test that our environment is set up properly, as shown in the following code:# echo "export CC=`pwd`/gcc-linaro-arm-linux-gnueabihf-4.8-2013.10_linux/bin/arm-linux-gnueabihf-" > bbb-vars
- Verify that the command worked. The
bbb-vars
file should appear in the directory as follows:root@debian:/home/user/bbb-tools# ls bbb-vars
- Set up the environment for a remote test by sourcing the
bbb-vars
file. Take a look at the command preceding the (.
) is the file location:root@debian:~# ./home/user/bbb-tools/bbb-vars
- Now, verify that the toolchain version we installed is correct using the following code:
root@debian:~# ${CC}gcc –-version arm-linux-gnueabihf-gcc (crosstool-NG linaro-1.13.1-4.8-2013.10 - Linaro GCC 2013.10) 4.8.2 20131014 (prerelease)Copyright (C) 2013 Free Software Foundation, Inc.This is free software; see the source for copying conditions. There is NOwarranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE
Part IV: Installing and setting up the Eclipse IDE
Perform the following steps:
- We will first install Eclipse on our VM with the following code:
root@debian:~# sudo apt-get install eclipse eclipse-cdt
Then, open Eclipse and set up a workspace by closing the welcome screen and navigating to Window | Show view | C/C++ Projects.
- Create a new C project by navigating to File | New | C Project.
- Give the project a name:
bbb_ground_control
. - Select Project type | Hello World ANSI C Project.
- Then, select Toolchain Cross GCC and click on Next.
- Enter the basic settings, such as the author name, in the next window.
- Click on Next to bring up the Select Configurations window.
- Now, click on the Advanced settings to bring up a Properties window.
- From the left-hand side, navigate to C/C++ Build | Settings to bring up Tool Settings for the Debug configuration.
- Choose the Tool Settings tab, then fill the Prefix and Path fields in the following manner:
Prefix:
arm-linux-gnueabihf-
Note
Be sure to include the hyphen (
-
) at the end of the preceding prefix.Path:
/home/user/bbb-tools/gcc-linaro-arm-linux-gnueabihf-4.8-2013.10_linux/bin
- Then, click on OK.
- This brings up another C Project window, which annoyingly asks you to repeat what you just did in the prior step. This may be a bug, but do it anyway:
Prefix:
arm-linux-gnueabihf-
Path:
/home/cah/bbb-tools/gcc-linaro-arm-linux-gnueabihf-4.8-2013.10_linux/bin
- Then, click on Finish.
- The sample code runs and you get an error:
Symbol 'EXIT_SUCCESS' could not be resolved
. Aaargh!The error says that some C code symbols cannot be resolved by the compiler. Not to worry though. This error can be ignored because according to the Eclipse documentation, it is inaccurate and does not affect the successful operation of the application.
- Now, we will build the project. On the Eclipse main menu, select Project | Build All. Then, open the Console window to see the build output messages. You should see the compiler prefix being used for the
gcc
compiler as follows:00:24:52 **** Build of configuration Debug for project bbb_ground_control ****make all Building file: ../src/bbb_ground_control.cInvoking: Cross GCC Compilerarm-linux-gnueabihf-gcc -O0 -g3 -Wall -c -fmessage-length=0 -MMD -MP -MF"src/ bbb_ground_control.d" -MT"src/ bbb_ground_control.d" -o "src/ bbb_ground_control.o" "../src/ bbb_ground_control.c"Finished building: ../src/ bbb_ground_control.c Building target: bbb_ground_control Invoking: Cross GCC Linkerarm-linux-gnueabihf-gcc -o " bbb_ground_control " ./src/ bbb_ground_control.o Finished building target: bbb_ground_control 00:24:52 Build Finished (took 172ms)
- For the Eclipse remote connection setup, on the main menu, click on Run | Run Configurations.
- Select C/C++ Remote Application. Click twice on this to open another dialog window.
- A drop-down option should show bbb_Hello_World Debug. Click on the New button in the middle of the window to create a project debug run configuration. Click on the New button next to Connection in the Main tab.
- This brings up the New Connection window.
- Select Linux and click on Next.
- This brings up a window with the connection information. Enter BeagleBone Black IP address for Host name and name the Connection name and Description both as
BeagleBone Black
:- Host name:
192.168.2.7
- Connection name:
Beaglebone Black
- Description:
Beaglebone Black
- Host name:
- Click on Next.
- In the New Connection/Files window, select the
select.ssh
files and then click on Next. - In the New Connection/Processes window, select
processes.shel.linux
. Then, click on Next. - In the New Connection/Shells window, select
ssh.shells
. Then, click on Next. - In the New Connection/Ssh Terminals window, select
ssh.terminals
and click on Finish. - You will end up back at the Run Configurations window. For Connection, choose BeagleBone Black, not Local.
- Click on Properties next to Connection. A window will come up, so select Remote workspace location.
- Enter a path to your project on BeagleBone Black. For the sake of simplicity, you should probably follow what we did and input
/root
. - Click on OK. This takes you back to the Run Configurations window.
In the following steps, we will perform two key things: configure our remote paths on the BBB and give our application permission to execute.
- At the bottom of the Run Configurations screen are two fields. Input the following:
remote absolute file path for C/C++ application:
/root/test_project/bbb_ground_control
commands to execute before application:
chmod +x /root/test_project/bbb_ground_control
Note
Choose a path on BeagleBone Black where the
bbb_ground_control
executable file will be placed. In our example, it is/root/test_project/bbb_ground_control
, wherebbb_ground_control
is the name of the binary file that we will compile. The purpose of thechmod +x
command is to give our program permission to execute. - Click on Apply. We are almost there. Be patient and hang on tight.
- From the terminal window on the VM, we have a couple more things to perform on the BBB itself, which is to mirror what we just input in the two fields in Eclipse. First, log in with the following code:
# sudo ssh 192.168.7.2
- Answer
yes
when promptedare you sure
. - Enter the root password for the BBB:
root
. You should now be logged in to the BBB. - Run the commands to duplicate what we just did in Eclipse, which means that we need to create a new directory, navigate to it and then run the following command to give the application permission to execute:
root@beaglebone:~# mkdir test_project root@beaglebone:~# cd test_project root@beaglebone:~# chmod a+w .
- Now, exit the SSH session on BeagleBone Black with the following code:
root@beaglebone:~# exit
- Back in the VM Eclipse window, click on Run.
- Another pop-up window will appear. Enter the user and password as
root
. Click on them and agree to the next few prompts from the BBB.The last few steps are focused on how to set up a remote debug session.
- In your terminal window, navigate to the project
Debug
path with the following code:# cd ~/bbb-eclipse-workspace/bbb_ground_control/Debug
- Now, we will perform a little obscure but necessary step when you run GDB: create an invisible file called
.gdbinit
. This is an initialization file that resides in the debug directory and automatically loads and parses when you run GDB.Typically, you would populate this file with any required commands. However, for our current recipe, the file remains empty, although it needs to remain present for GDB's proper operation.
- We could use
nano
to create the file because we used this editor in the earlier chapters. However, there is another command that actually generates the file on the fly, saves it, and places it in whatever directory you have entered, as shown in the following code:# touch .gdbinit
- Make sure that the file was created with the following code:
# ls
Hmm. It isn't there!
To figure out what is happening, this is a case where using different options with a command is vital. With the
ls
command, we want to append the command with the-a
option. So, try again using the following code:# ls -a
The
gdbinit
file should now appear in the directory's lineup. - Back in the Eclipse window, select Window | Open Perspective | Other. Then, select Debug. This will shift the window views to a debug-centric UI.
- From the top menu, select Run | Debug Configurations. In the window that opens, select C/C++ Remote Application | bbb_ground_control Debug.
Hold on tight. Almost done.
- Select the Debugger tab. This shows us more tabs because we haven't had our fill of tabs or options yet.
- Now, select the Main tab. Here, we need to populate the two fields: GDB Debugger (the executable in the toolchain directory) and the GDB command file (the directory where we created the .gdbinit file). To facilitate this step, you should be able to browse the relevant directories and grab the right paths as follows:
GDB Debugger:
/home/user/bbb-tools/gcc-linaro-arm-linux-gnueabihf-4.8-2013.10_linux/bin/arm-linux-gnueabihf-gdb
GDB command file:
/home/user/bbb-eclipse-workspace/bbb_ground_control/Debug/.gdbinit
- Then, click on Apply. I like this part.
- Now, we finally get to test the whole shebang with Debug run. Let me repeat and this time with bugles and proper fanfare: we will test everything we just did and start a Debug session.
So, at the bottom of the still open window, click on Debug. Hold your breath! This will start the remote session with the BBB and finish the cycle just after the
main()
line in your.c
file.Note
You may get another login prompt from your BeagleBone Black. Just do the same drill:
user = root
andpassword = root
.If all went as planned and the gremlins stay home, you should see the following output on your Eclipse console screen:
Last login: DAY MO DATE TIME YEAR from 192.168.7.1 echo $PWD'>' chmod +x /root/test_project/bbb_ground_control;gdbserver :2345 /root/test_project/bbb_ground_control;exit root@beaglebone:~# echo $PWD'>' /root> root@beaglebone:~# chmod +x /root/test_project/bbb_ground_control;gdbserver :2345 /root/test_project/bbb_ground_control;exit Process /root/test_project/bbb_ground_control created; pid = 2910 Listening on port 2345 Remote debugging from host 192.168.7.1
- Since the ultimate goal of all this effort was to actually perform some debugging on a program, now you can really get to work. Make sure your
bbb_ground_control.c
window is selected. Then, at the top, choose Run. - From the drop-down list, you will see the basket of debug commands now ready for your able, debug-twitchy fingers.
- If you made it to this point, this recipe has one last set of command ingredients:
# Go to actual cabinet on actual shelf # Take out bottle of single malt scotch # Pour dram, perhaps two # Lean back head and drink # Congratulate Major Tom on a good test flight
There's more…
A thorough review of how to debug is beyond the scope of this book. Fortunately, there are ample resources to learn more. Here are a few:
- RMS's gdb debugger tutorial is available at http://www.unknownroad.com/rtfm/gdbtut/gdbtoc.html
- For a deeper understanding of GDB and the
.gdbinit
file, refer to http://www.dirac.org/linux/gdb/03-Initialization,_Listing,_And_Running.php
There's more…
A thorough review of how to debug is beyond the scope of this book. Fortunately, there are ample resources to learn more. Here are a few:
- RMS's gdb debugger tutorial is available at http://www.unknownroad.com/rtfm/gdbtut/gdbtoc.html
- For a deeper understanding of GDB and the
.gdbinit
file, refer to http://www.dirac.org/linux/gdb/03-Initialization,_Listing,_And_Running.php
systemd services
First, it wasn't a typo to label this section as systemd in all lowercase letters. It is one of the mandates of Linux that any daemon, which is what systemd is, should be in lowercase. Also, daemons must also come with the lowercase suffix: d.
So what is systemd exactly? Briefly, it is a background process and a system management daemon for managing user space system services. Systemd will become standard plumbing for most major Linux distros and is an integral part of the BBB Debian distribution. It is the first process initiated on bootup in the Linux user space and the last process to terminate on shutdown. Basically, systemd starts the show on your Linux OS and turns out the lights as it's leaving.
Sound familiar? If it does, that's because systemd is the heir to init: Linux's longtime daemon of daemons.
Mastering systemd on your BBB helps us better understand system dependencies because systemd serves as a robust framework for these dependencies. Here are a couple of examples of why you'd want to manipulate systemd processes:
- Bootup: Since much is happening with your system at bootup, it makes sense to have tighter control and deeper insight into the startup processes. For example, you may want to optimize your system to squeeze out more CPU resources for higher resolution video display. With systemd, it's easier to control that load environment.
- Job scheduling: You may have created a beautiful prototype for a weather measurement device. However, you had in mind a wireless, battery-driven design, so power consumption is a concern. In this case, you can use systemd to schedule runtimes (systemd Calendar Timers) for the sensors to capture and transmit data and then revert to sleep mode when not needed, thereby prolonging the battery life.
There's more…
Before we move on to the recipes, you'll find a great deal of deeper insight into systemd by taking a look at some of the following referenced material:
- The definitive (freedesktop.org) resource for systemd is available at http://www.freedesktop.org/wiki/Software/systemd/
- The quick reference cheat sheet for systemd commands is available at http://dynacont.net/documentation/linux/Useful_SystemD_commands/
man systemd
: This is the command for the very extensive manual for the daemon. It yields more information than you would probably ever want to know about systemd. However, it is there if you want it.- If you want the full background on how systemd came to be, one of the creators of the tool provides the full story and context at http://0pointer.de/blog/projects/systemd.html
See also
systemd is far from perfect. Many Linux heads gripe about it being too powerful and potentially becoming overly complicated for users. Here is some background on this controversy:
- A robust slashdot thread provides plenty of rants on the pros and cons at http://news.slashdot.org/story/14/02/14/166255/ubuntu-to-switch-to-systemd
- Eric Steven Raymond (ESR), an open source guru, is currently on the fence about systemd at http://interviews.slashdot.org/story/14/03/10/137246/interviews-esr-answers-your-questions
Despite the disagreements over its long-term impact on Linux, systemd is here to stay at least for the foreseeable future. So, it behooves you to learn some recipes.
There's more…
Before we move on to the recipes, you'll find a great deal of deeper insight into systemd by taking a look at some of the following referenced material:
- The definitive (freedesktop.org) resource for systemd is available at http://www.freedesktop.org/wiki/Software/systemd/
- The quick reference cheat sheet for systemd commands is available at http://dynacont.net/documentation/linux/Useful_SystemD_commands/
man systemd
: This is the command for the very extensive manual for the daemon. It yields more information than you would probably ever want to know about systemd. However, it is there if you want it.- If you want the full background on how systemd came to be, one of the creators of the tool provides the full story and context at http://0pointer.de/blog/projects/systemd.html
See also
systemd is far from perfect. Many Linux heads gripe about it being too powerful and potentially becoming overly complicated for users. Here is some background on this controversy:
- A robust slashdot thread provides plenty of rants on the pros and cons at http://news.slashdot.org/story/14/02/14/166255/ubuntu-to-switch-to-systemd
- Eric Steven Raymond (ESR), an open source guru, is currently on the fence about systemd at http://interviews.slashdot.org/story/14/03/10/137246/interviews-esr-answers-your-questions
Despite the disagreements over its long-term impact on Linux, systemd is here to stay at least for the foreseeable future. So, it behooves you to learn some recipes.
See also
systemd is far from perfect. Many Linux heads gripe about it being too powerful and potentially becoming overly complicated for users. Here is some background on this controversy:
- A robust slashdot thread provides plenty of rants on the pros and cons at http://news.slashdot.org/story/14/02/14/166255/ubuntu-to-switch-to-systemd
- Eric Steven Raymond (ESR), an open source guru, is currently on the fence about systemd at http://interviews.slashdot.org/story/14/03/10/137246/interviews-esr-answers-your-questions
Despite the disagreements over its long-term impact on Linux, systemd is here to stay at least for the foreseeable future. So, it behooves you to learn some recipes.
Basic commands for systemd services
systemd is modified via a configuration file, rather than a shell script. Before you perform anything too ambitious, we will take a look at how we stop, start, enable, and disable a service.
Our example will reset and reconfigure a key service that will run in your Debian distribution: the systemd-timedated.service
by default.
How to do it...
Perform the following steps:
- Navigate to the
systemd
directory (root user) with the following code:# cd /lib/systemd/system
- Let's see what services are running, using a command that serves as the control utility for
systemd
, as shown in the following code:# systemctl
You should see a long, fat list of services that show their current status on the system. The items appended with the
.service
filename aresystemd
services and controllable via the command line. - Run this command to stop the service:
systemctl stop systemd-timedated.service
- Now, disable the service using the following code:
systemctl disable systemd-timedated.service
- Then, do the opposite and enable it as follows:
Systemctl enable systemd-timedated.service
- Although your service may be enabled, you need to actually start it so that the system has access to its routine, as shown in the following code:
systemctl start systemd-timedated.service
- Finally, check whether the service is running correctly with the following code:
systemctl status systemd-timedated.service
There's more…
A handy list of systemd commands is available as a downloadable PDF or an online reference at http://www.cheatography.com/tme520/cheat-sheets/systemd/.
How to do it...
Perform the following steps:
- Navigate to the
systemd
directory (root user) with the following code:# cd /lib/systemd/system
- Let's see what services are running, using a command that serves as the control utility for
systemd
, as shown in the following code:# systemctl
You should see a long, fat list of services that show their current status on the system. The items appended with the
.service
filename aresystemd
services and controllable via the command line. - Run this command to stop the service:
systemctl stop systemd-timedated.service
- Now, disable the service using the following code:
systemctl disable systemd-timedated.service
- Then, do the opposite and enable it as follows:
Systemctl enable systemd-timedated.service
- Although your service may be enabled, you need to actually start it so that the system has access to its routine, as shown in the following code:
systemctl start systemd-timedated.service
- Finally, check whether the service is running correctly with the following code:
systemctl status systemd-timedated.service
There's more…
A handy list of systemd commands is available as a downloadable PDF or an online reference at http://www.cheatography.com/tme520/cheat-sheets/systemd/.
There's more…
A handy list of systemd commands is available as a downloadable PDF or an online reference at http://www.cheatography.com/tme520/cheat-sheets/systemd/.
Optimize boot time
You can use systemd to speed up your startup time. This recipe is not a definitive recommendation for which services may be expendable. Instead, it provides the overall method to test the impact of different services on your boot time.
How to do it...
Perform the following steps:
- Navigate to the
systemd
directory (root user) as follows:# cd /lib/systemd/system
- Next, determine how long your overall system is taking to get going with the following code:
# systemd-analyze
- You can quickly figure out the pokier services. Just point the finger at them with the following command that reveals all the systemd services that are sorted by their boot times:
# systemd-analyze blame
- From this output, you can immediately pinpoint some of the culprits. We will assume that you're running the current Debian distro, so you'll see things similar to the following command:
wicd.service (7205ms) apache2.service (3430ms) wpa_supplicant.service (1938ms) ...
- Some of these may be expendable startup services and worth disabling. Experiment by disabling the different services and see how it affects your boot times. Here is an example:
# systemd systemctl disable wicd.service
How to do it...
Perform the following steps:
- Navigate to the
systemd
directory (root user) as follows:# cd /lib/systemd/system
- Next, determine how long your overall system is taking to get going with the following code:
# systemd-analyze
- You can quickly figure out the pokier services. Just point the finger at them with the following command that reveals all the systemd services that are sorted by their boot times:
# systemd-analyze blame
- From this output, you can immediately pinpoint some of the culprits. We will assume that you're running the current Debian distro, so you'll see things similar to the following command:
wicd.service (7205ms) apache2.service (3430ms) wpa_supplicant.service (1938ms) ...
- Some of these may be expendable startup services and worth disabling. Experiment by disabling the different services and see how it affects your boot times. Here is an example:
# systemd systemctl disable wicd.service
Create a systemd service to run at boot time
Remember those ancient days of Chapter 2, Basic Programming Recipes, when you were just learning how to send an e-mail with Node.js? No? You skipped that recipe? Well, you may want to do that one before you dive into this one. In this recipe, we'll perform something similar and have the script run at boot up. Instead of having Node.js perform the job, it'll be Python and systemd.
The scenario is that you need to control your BBB remotely via SSH or VNC, but the board is offsite or running headless. As you have learned previously, in order to control the BBB remotely, we have to know the board's IP address. If you're in front of the board, it's easy enough to check the IP at the bottom of your screen via the GUI popup. However, our board is 100 miles away and isn't attached to a display. Systemd (with a healthy dash of Python) comes to the rescue!
Let's take a look at how we can have systemd send us this magical IP-addressed e-mail.
How to do it...
Perform the following steps:
- Log in as root with the following code:
sudo -i
- Then, create a new Python file called
email-ip.py
and save it, as shown in the following code:sudo nano email-ip-BBB.py
- Here is the Python code (the code is derived from the example code on stackoverflow at http://bit.ly/1kUppmT):
#!/usr/bin/python ##Look up your BBB's ip address and email it## import socket import datetime, time import sys # Import smtplib for the actual sending function import smtplib # Import the email modules we'll need from email.mime.text import MIMEText try: b = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) b.connect(("8.8.8.8",80)) bbb1_ip = b.getsockname()[0] b.close() except SocketError: print sys.exc_info()[0] except: print error time.sleep(5) msg = MIMEText("Beaglebone Black ip address: %s" % bbb1_ip) From = 'yourname@youremaildomain.com' To = 'recipientemail@recipientdomain.com' #include module for date and time msg['Subject'] = 'BBB ip address at ' + str(datetime.datetime.now()) msg['From'] = From msg['To'] = To # Send the message via our own SMTP server, but don't include the # envelope header. s = smtplib.SMTP('smtp.gmail.com', 587) s.starttls() s.login('your-name@gmail.com', your-password') s.sendmail(From, [To], msg.as_string()) s.quit()
In our recipe, we've used a Gmail account as the server and user credentials, although you can use any service you prefer. Just replace the Gmail details with your preferred provider.
- Navigate to the
systemd
directory with the following code:# cd /lib/systemd/system
- Now, create a new service file as follows:
# nano email-ip.service
- Copy and paste the following code to the
nano
window. Let's take a look at the systemd code in its entirety first. Then, we'll break down its meaning as follows:[Unit] Description=Email current IP Address [Service] WorkingDirectory=/home/debian/ ExecStart=/usr/bin/python email-ip-bbb.py SyslogIdentifier=emailip Restart=on-failure RestartSec=5 [Install] WantedBy=multi-user.target
- What does this all mean? First, let's begin with inputting a human-readable name for the systemd service, which describes the properties of the process you'd like to run, as shown in the following code:
[Unit] Description=Email current IP Address
- Next, we will describe where the file is that will be run on bootup with the following code:
[Service] WorkingDirectory=/home/debian/
- Then, we will tell the service about the command or script to be executed for the file:
ExecStart=/usr/bin/python email-ip.py
- Now, the system logs should capture the run data, so we have to give the service a unique name for that purpose as follows:
SyslogIdentifier=emailip
- We have to prepare for the application exiting with an error, tell it not to despair, and try again with the following code:
Restart=on-failure
- Now, not only should the service try again, but keep trying to relaunch, in this case, every 5 seconds, as shown in the following code:
RestartSec=5
- Once the service is enabled, we want to give it a run-level target, in our case, tell it to launch as part of a group of processes—the multi-user processes—that trigger near the end of the boot cycle as follows:
[Install] WantedBy=multi-user.target
- Save the file and then enable the service you just created:
root@beaglebone:/lib/systemd/system# systemctl enable email-ip.service
- Now, reboot. If everything went as planned, you should get an e-mail in your inbox that tells you the IP address of your BeagleBone Black. Pretty handy!
How to do it...
Perform the following steps:
- Log in as root with the following code:
sudo -i
- Then, create a new Python file called
email-ip.py
and save it, as shown in the following code:sudo nano email-ip-BBB.py
- Here is the Python code (the code is derived from the example code on stackoverflow at http://bit.ly/1kUppmT):
#!/usr/bin/python ##Look up your BBB's ip address and email it## import socket import datetime, time import sys # Import smtplib for the actual sending function import smtplib # Import the email modules we'll need from email.mime.text import MIMEText try: b = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) b.connect(("8.8.8.8",80)) bbb1_ip = b.getsockname()[0] b.close() except SocketError: print sys.exc_info()[0] except: print error time.sleep(5) msg = MIMEText("Beaglebone Black ip address: %s" % bbb1_ip) From = 'yourname@youremaildomain.com' To = 'recipientemail@recipientdomain.com' #include module for date and time msg['Subject'] = 'BBB ip address at ' + str(datetime.datetime.now()) msg['From'] = From msg['To'] = To # Send the message via our own SMTP server, but don't include the # envelope header. s = smtplib.SMTP('smtp.gmail.com', 587) s.starttls() s.login('your-name@gmail.com', your-password') s.sendmail(From, [To], msg.as_string()) s.quit()
In our recipe, we've used a Gmail account as the server and user credentials, although you can use any service you prefer. Just replace the Gmail details with your preferred provider.
- Navigate to the
systemd
directory with the following code:# cd /lib/systemd/system
- Now, create a new service file as follows:
# nano email-ip.service
- Copy and paste the following code to the
nano
window. Let's take a look at the systemd code in its entirety first. Then, we'll break down its meaning as follows:[Unit] Description=Email current IP Address [Service] WorkingDirectory=/home/debian/ ExecStart=/usr/bin/python email-ip-bbb.py SyslogIdentifier=emailip Restart=on-failure RestartSec=5 [Install] WantedBy=multi-user.target
- What does this all mean? First, let's begin with inputting a human-readable name for the systemd service, which describes the properties of the process you'd like to run, as shown in the following code:
[Unit] Description=Email current IP Address
- Next, we will describe where the file is that will be run on bootup with the following code:
[Service] WorkingDirectory=/home/debian/
- Then, we will tell the service about the command or script to be executed for the file:
ExecStart=/usr/bin/python email-ip.py
- Now, the system logs should capture the run data, so we have to give the service a unique name for that purpose as follows:
SyslogIdentifier=emailip
- We have to prepare for the application exiting with an error, tell it not to despair, and try again with the following code:
Restart=on-failure
- Now, not only should the service try again, but keep trying to relaunch, in this case, every 5 seconds, as shown in the following code:
RestartSec=5
- Once the service is enabled, we want to give it a run-level target, in our case, tell it to launch as part of a group of processes—the multi-user processes—that trigger near the end of the boot cycle as follows:
[Install] WantedBy=multi-user.target
- Save the file and then enable the service you just created:
root@beaglebone:/lib/systemd/system# systemctl enable email-ip.service
- Now, reboot. If everything went as planned, you should get an e-mail in your inbox that tells you the IP address of your BeagleBone Black. Pretty handy!