App Setup Using runit - FreeWaveTechnologies/ZumIQ GitHub Wiki

This procedure describes the basic steps needed to get an app installed and running in the ZumIQ environment using runit.

Note that while this procedure uses the pre-installed "runit" package and the default directory structure (see Linux Environment), developers are under no obligation to follow this specific procedure. However, by using this procedure FreeWave technical support will be better able to help with app installation and operation issues should they arise.

For firmware versions v1.3.1.1 and later, systemctl and Docker are also available. See the wiki pages App Setup using systemctl and App Setup Using Docker.

Contents

Hello World Examples

This repository contains a number of Hello World examples for a variety of programming languages and platforms. Each of these shell scripts creates a simple "Hello World" web app, following the procedure documented below.

Current examples are given for:

  • Node.js
  • Node-RED
  • Python 2
  • Python 3

Installing and Starting

App installation and startup will be demonstrated by with a simple Python 2 web app, built on the Flask web framework.

The basic procedure is:

  1. Install Prerequisites
  2. Create App Directory
  3. Copy App Files to Device
  4. Edit "run" Script
  5. Create Service Link

1. Install Prerequisites

First, ensure that the package index is up-to-date:

sudo apt-get update

(Optional) Upgrade any existing packages:

sudo apt-get upgrade

Python 2 is on the device by default, however for version 1.0.6, pip, the Python package manager, needs to be manually installed. Skip this step if using version 1.1.0 or higher:

sudo apt-get install python-pip

Finally, use pip to install the Flask module:

sudo pip install flask

2. Create App Directory

Login to the device as devuser (see Logging In)

Change directory to /home/devuser/apps

cd ~/apps

Create an app directory using the template directory. (This will create a placeholder run script):

cp -r template HelloDemo

3. Copy App Files to Device

App files must be manually copied to the device using one of the techniques described on the Transfer Files page.

NOTE: If you copy the files to the device using the PTP Drag-and-Drop or Website, you will need to move the files from the upload location in the /ptp directory to the app directory created above. Assuming the file is named hello.py:

cd /ptp
mv hello.py ~/apps/HelloPython 

NOTE: If you copy the files to the device using SCP, you have the option of copying the files directly into the app directory created above.

For simple examples such as this one, the files can be created and edited directly on the device in the app directory.

For the purpose of this example, we will assume that you have a file named hello.py located in /home/devuser/apps/HelloDemo, containing the following code:

from flask import Flask
app = Flask(__name__)

@app.route("/")
def hello():
    return "Hello World!"

if __name__ == "__main__":
    app.run(host='0.0.0.0')

4. Edit "run" Script

Edit the run script to contain whatever commands are necessary to start the application (the vi (vim) editor is available by default. nano can be installed by running the command sudo apt-get install nano). For this example, the run script should contain the following:

#!/bin/sh

exec python hello.py

IMPORTANT: Be sure to start your app in the script with the exec command. This is necessary for the runsv process to control the running app.

If you create the run script from scratch, ensure that it is executable by using the chmod command:

chmod +x run

5. Create Service Link

By default, the runsv service (part of the "runit" package) looks for subdirectories containing "run" scripts in the /home/devuser/service directory. For the service to start automatically, create a symbolic link to the app directory in the service directory:

cd ~/service
ln -s ~/apps/HelloDemo HelloDemo

The runsv service will automatically pick up the change and start your application immediately, as well as starting it after a reboot.

You can verify that the app is running by using ps:

ps -ef

This will result in something like the following:

UID        PID  PPID  C STIME TTY          TIME CMD
devuser   1448     1  0 Aug28 ?        00:00:01 runsvdir -P /home/devuser/service
devuser   1505  1493  0 15:18 pts/0    00:00:00 /bin/bash
devuser   1523  1448  0 15:18 ?        00:00:00 runsv HelloDemo
devuser   1524  1523  0 15:18 ?        00:00:00 /bin/sh ./run
devuser   1525  1524  1 15:18 ?        00:00:01 python hello.py
devuser   1532  1505  0 15:20 pts/0    00:00:00 ps -ef

Note that there are three processes involved:

  1. "runsvdir -P /home/devuser/service" monitors the service directory for services to run.
  2. "runsv HelloDemo" is the service wrapper for the app.
  3. "python hello.py" is the actual running app process.

Finally, to verify that the app is actually functioning as expected, in a web browser, go to <IP address>:5000. The website should respond with "Hello, World!":

Installation Helper Script

The helper script add-service.sh is included to help in getting an app running as a service. It's located in /home/devuser/bin which is in the path by default. It will create the "run" script and service link automatically.

To use, you first need to complete steps 1-3 in Installing and Starting above, to get the app files onto the device. Note that this script requires that you place your app in a subdirectory under /home/devuser/apps.

Usage:

add-service.sh <app folder name> <app startup command(s)>

For the example in Installing and Starting above, this looks like:

add-service.sh HelloDemo "python hello.py"

This will create a "run" script automatically in /home/devuser/apps/HelloDemo with the following contents:

#!/bin/bash
exec 2>&1
exec python hello.py

The exec 2>&1 command redirects stderr to stdout. This is necessary since this script will also start the svlogd service to log output from the app. It can be seen by again running ps -ef to sett the running processes:

UID        PID  PPID  C STIME TTY          TIME CMD
devuser   1445     1  0 17:01 ?        00:00:00 runsvdir -P /home/devuser/service
devuser   1472  1460  0 17:02 pts/0    00:00:00 /bin/bash
devuser   1892  1445  0 17:06 ?        00:00:00 runsv HelloDemo
devuser   1893  1892  0 17:06 ?        00:00:00 /usr/bin/svlogd --tt ../logs
devuser   1894  1892  1 17:06 ?        00:00:01 python hello.py
devuser   1901  1472  0 17:08 pts/0    00:00:00 ps -ef

When an app is set up using the add-service.sh script, all stderr and stdout output will be redirected to the log file in /home/devuser/apps/app-subfolder/logs/current. In the example above, this is /home/devuser/apps/HelloDemo/logs/current.

NOTE: Using the add-service.sh script is entirely optional. It is provided as a starting point for understanding how to install and run apps as services, but it is not intended to represent the definitive procedure. Do whatever works best for your application.

Stopping the App

If the app subdirectory and service links are configured as described above in Installing and Starting or Installation Helper Script, the app will start automatically as a service when created and will start up whenever the device reboots.

The simplest way to stop the app is to simply remove the service link. The runsv service will detect this change and kill the running service.

rm ~/service/HelloDemo

You can then confirm that the service runner and application have been terminated by again running the ps -ef command. You should see something like this:

UID        PID  PPID  C STIME TTY          TIME CMD
devuser   1445     1  0 17:01 ?        00:00:00 runsvdir -P /home/devuser/service
devuser   1472  1460  0 17:02 pts/0    00:00:00 /bin/bash
devuser   2020  1472  0 19:44 pts/0    00:00:00 ps -ef

indicating that the service has been stopped.

Keep in mind that while effective, this is a brute-force way to manage the state of the running application. For more precise control, see the Advanced App Control in the following section.

Advanced App Control

Services can be managed with a finer grain of control using the capabilities provided by the "runit" package. For comprehensive documentation on how to use those capabilities, including using the sv program to control service, see the documentation at the runit web site.

sv Example

Assuming that the HelloDemo app is up and running, stop the service using the following command:

sv down ~/service/HelloDemo

Note that the full path to the service directory must be provided. Running ps -ef now indicates that only the "python hello.py" process has been terminated. The "runsv HelloDemo" service manager is still active, waiting for signals from the sv program:

UID        PID  PPID  C STIME TTY          TIME CMD
devuser   1445     1  0 17:01 ?        00:00:00 runsvdir -P /home/devuser/service
devuser   1472  1460  0 17:02 pts/0    00:00:00 /bin/bash
devuser   2026  1445  0 19:51 ?        00:00:00 runsv HelloDemo
devuser   2027  2026  0 19:51 ?        00:00:00 /usr/bin/svlogd --tt ../logs
devuser   2045  1472  0 19:58 pts/0    00:00:00 ps -ef

Start the service back up using the following command:

sv up ~/service/HelloDemo

Again, running ps -ef will show that the "python hello.py" process has been started:

UID        PID  PPID  C STIME TTY          TIME CMD
devuser   1445     1  0 17:01 ?        00:00:00 runsvdir -P /home/devuser/service
devuser   1472  1460  0 17:02 pts/0    00:00:00 /bin/bash
devuser   2026  1445  0 19:51 ?        00:00:00 runsv HelloDemo
devuser   2027  2026  0 19:51 ?        00:00:00 /usr/bin/svlogd --tt ../logs
devuser   2047  2026 43 19:59 ?        00:00:01 python hello.py
devuser   2050  1472  0 19:59 pts/0    00:00:00 ps -ef

For more information see the sv man page for details on using sv to manage running services.

⚠️ **GitHub.com Fallback** ⚠️