This recipe uses a virtual Android device as the target platform that we just created to show the usage of BusyBox applets on an embedded platform. It will replace the Android toolbox
mksh shell-based console with the more powerful BusyBox
ash shell-based console. It starts a remote shell and a web service on it with BusyBox
The console based on BusyBox
ash gives a more powerful shell environment. Not only can the applets be run on this console, but new shell scripts can also be written in such a shell environment.
The remote shell is useful for remote development and maintenance, and the web service is helpful for system monitoring. Both of them have common use cases in an embedded system.
At this stage, we aren't constructing a full bootable filesystem from scratch, but only using the BusyBox applets. So, for simplicity and ease of testing, we will install our compiled BusyBox binary and scripts into an existing Android
At first, get a copy of the existing
ramdisk.img; its path can be found at
~/.android/avd/busybox-avd.avd/hardware-qemu.ini; for example,
Three examples will be shown in this section to demonstrate the usage of the BusyBox applets on a virtual Android device.
Replace the console based on Android mksh with the BusyBox ash console.
Since the Android toolbox
mkshshell is too lightweight, and the Android toolbox (the BusyBox-like toolset software) itself only provides a few of the applets, here it only shows us how to replace it with BusyBox
ashas the default console, and eventually build a more powerful shell environment.
At first, decompress the original ramdisk image with the following steps:
$ mv ramdisk.img ramdisk.img.gz $ gunzip ramdisk.img.gz $ mkdir ramdisk/ && cd ramdisk/ $ cpio -i -F ../ramdisk.img
Second, get a prebuilt BusyBox binary,
busybox-armv7l, and put it into
$ wget http://busybox.net/downloads/binaries/latest/busybox-armv7l $ cp busybox-armv7l ramdisk/
Third, to install BusyBox at runtime, let's prepare a script and name it
busybox-console.sh, and add it into
#!/system/bin/sh # busybox-console.sh -- Install busybox to /bin and start /bin/ash # remount root file system for read and write mount -o remount,rw / mkdir /bin chmod 0777 /bin/ chmod 0777 /busybox-armv7l /busybox-armv7l --install -s /bin export SHELL=/bin/ash /bin/ash
It remounts the root filesystem to be readable and writable and allows us to install BusyBox with
/binat runtime; lastly, it starts
$ cp busybox-console.sh ramdisk/
Then start a service in
init.rcto launch the previous script. Add a
chmodcommand to make sure the previous script is executable.
$ cd ramdisk/ $ sed -i '/loglevel/a \\n chmod 0777 /busybox-console.sh' init.rc
Let the BusyBox applets be executed directly without the full path.
Append the installation directory of the BusyBox applet,
/bin, to the default
$ sed -i -e "s#export PATH #export PATH /bin:#g" init.rc
Replace the original console service with our console service that is based on
$ sed -i -e "s#service console.*#service console /bin/busybox.sh#g" init.rc
Now back up the old ramdisk and recompress a new one.
$ mv ramdisk.img ramdisk-backup.img $ cd ramdisk/ $ find . | cpio -H newc -o | gzip -9 > ../ramdisk.img
Lastly, run the emulator to start with our new ramdisk and with the BusyBox
$ emulator @busybox-emulator -ramdisk ./ramdisk.img -shell -show-kernel / # echo $SHELL /bin/ash / # ls /bin [ fold mke2fs setsid (truncated to fit in the text) / # which ls /bin/ls
This code only lists a part of the applets installed. As we can see, the shell becomes
/bin/ash. The applets are installed under
lscommand is not the one provided by Android toolbox (
/system/bin/ls) but the one (
/bin/ls) installed by BusyBox. This indicates that we have successfully changed the console service to our own.
The writing of new shell scripts under this shell environment based on
ashwill be introduced in the Enhancing system stability of an embedded (Android) system recipe.
Start a remote shell with BusyBox
A real embedded system may have no serial port and adb and no local cable connected, but a network connection with Wi-Fi or 3G; accessing such systems may need a remote shell. As a lot of remote shells exist, such as SSH and Telnet, and since BusyBox doesn't provide an SSH daemon but
telnetd, we use
telnetdas an example here.
Firstly, start the service on an emulator from a virtual serial port.
/ # echo "Hello, telnetd" > /data/telnetd.issue / # telnetd -f /data/telnetd.issue -p 3333 / # ps | grep telnetd | grep -v grep 731 0 0:00 telnetd -f /data/telnetd.issue -p 3333
Second, build an emulated network connection. Android emulator does not provide a standalone full emulated network stack but a port-redirection-based network stack. In order to use the network service, the
adb forwardcommand should be used to enable the port redirection feature.
Say you want to access the
telnetdservice seen previously. The remote tcp:3333
of the emulator must be redirected to a port of our desktop development system (for example, tcp:3333) by running the following command:
$ adb forward tcp:3333 tcp:3333
Third, log in to the telnet service and issue the following command on the development system:
$ telnet localhost 3333 Hello, telnetd localhost login:
It means it really logs in and gets a prompt,
Hello, telnetd. However, without a user account and the password, we cannot log in. To avoid setting up a username and password, we can simply let
/bin/login, then no login progress will be required. Let's start
telnetdon the emulator as follows:
/ # telnetd -p 3333 -f /data/telnetd.issue -l /bin/ash
Log in to the shell directly and experiment with our Android device remotely.
Start a web server with
/data/www, and create a simple HTML page on the target platform from a virtual serial port as follows:
/ # mkdir /data/www / # httpd -h /data/www -p 8080 / # cat > /data/www/index.html <!doctype html><html><head><title>BusyBox</title></head><body><h1>Hello, Busybox Http Server Works.</h1></body></html>
Second, just like
telnetd, make a port redirection from the emulator to the development system.
# adb forward tcp:8080 tcp:8080
Lastly, let's access the
httpdservice with any modern web browser on our development system. Here we use the Chromium browser as an example:
BusyBox applets cover the standard coreutils, console tools, e2fsprogs, procps, SELinux, editors, modutils, debianutils, login-utils, networking, sysklogd, util-linux, findutils, mailutils, printutils, and even a tiny shell interpreter. This recipe shows how to install some of them at runtime on an existing Android system and demonstrates the working of these three applets:
To add more function for an embedded system, the other applets may also need to be configured via the configuration utility and used based on their full usage information with the
In order to start the previously mentioned service during boot, we can add
telnetd in the previous
# Start httpd service httpd -h /data/www -p 8080 # Start telnetd service telnetd -f /data/telnetd.issue -p 3333 -l /bin/ash
To access them, we must also forward the remote ports to the development system as follows:
$ adb forward tcp:3333 tcp:3333 $ adb forward tcp:8080 tcp:8080